2001-12-14 09:13:43 +01:00
|
|
|
/*
|
|
|
|
* ngIRCd -- The Next Generation IRC Daemon
|
2010-02-10 23:40:03 +01:00
|
|
|
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
|
2001-12-14 09:13:43 +01:00
|
|
|
*
|
2002-12-12 13:24:18 +01:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
* Please read the file COPYING, README and AUTHORS for more information.
|
2001-12-14 09:13:43 +01:00
|
|
|
*/
|
|
|
|
|
2002-01-04 02:21:22 +01:00
|
|
|
#define __client_c__
|
|
|
|
|
2002-03-12 15:37:51 +01:00
|
|
|
#include "portab.h"
|
2001-12-14 09:13:43 +01:00
|
|
|
|
2010-12-27 17:14:14 +01:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* Client management.
|
|
|
|
*/
|
|
|
|
|
2002-03-12 15:37:51 +01:00
|
|
|
#include "imp.h"
|
2001-12-14 09:13:43 +01:00
|
|
|
#include <assert.h>
|
2001-12-23 23:04:37 +01:00
|
|
|
#include <unistd.h>
|
2001-12-27 17:54:51 +01:00
|
|
|
#include <stdio.h>
|
2002-01-01 19:25:44 +01:00
|
|
|
#include <stdlib.h>
|
2001-12-23 23:04:37 +01:00
|
|
|
#include <string.h>
|
2004-01-17 04:17:49 +01:00
|
|
|
#include <strings.h>
|
2001-12-27 18:15:29 +01:00
|
|
|
#include <netdb.h>
|
2001-12-14 09:13:43 +01:00
|
|
|
|
2005-04-27 09:46:50 +02:00
|
|
|
#include "defines.h"
|
2002-05-27 15:09:26 +02:00
|
|
|
#include "conn.h"
|
|
|
|
|
2002-03-12 15:37:51 +01:00
|
|
|
#include "exp.h"
|
2001-12-26 15:45:37 +01:00
|
|
|
#include "client.h"
|
|
|
|
|
|
|
|
#include <imp.h>
|
2002-01-06 16:18:14 +01:00
|
|
|
#include "ngircd.h"
|
2001-12-14 09:13:43 +01:00
|
|
|
#include "channel.h"
|
2001-12-30 20:26:11 +01:00
|
|
|
#include "conf.h"
|
2002-03-25 17:59:36 +01:00
|
|
|
#include "hash.h"
|
2002-02-28 00:23:53 +01:00
|
|
|
#include "irc-write.h"
|
2001-12-14 09:13:43 +01:00
|
|
|
#include "log.h"
|
2001-12-26 15:45:37 +01:00
|
|
|
#include "messages.h"
|
2001-12-14 09:13:43 +01:00
|
|
|
|
|
|
|
#include <exp.h>
|
2001-12-26 15:45:37 +01:00
|
|
|
|
2002-10-04 14:39:58 +02:00
|
|
|
#define GETID_LEN (CLIENT_NICK_LEN-1) + 1 + (CLIENT_USER_LEN-1) + 1 + (CLIENT_HOST_LEN-1) + 1
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static CLIENT *This_Server, *My_Clients;
|
2001-12-14 09:13:43 +01:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static WHOWAS My_Whowas[MAX_WHOWAS];
|
|
|
|
static int Last_Whowas = -1;
|
2008-04-04 21:30:01 +02:00
|
|
|
static long Max_Users, My_Max_Users;
|
2005-05-16 14:23:48 +02:00
|
|
|
|
2001-12-14 09:13:43 +01:00
|
|
|
|
2006-10-07 12:40:52 +02:00
|
|
|
static unsigned long Count PARAMS(( CLIENT_TYPE Type ));
|
|
|
|
static unsigned long MyCount PARAMS(( CLIENT_TYPE Type ));
|
2002-01-16 23:10:35 +01:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static CLIENT *New_Client_Struct PARAMS(( void ));
|
|
|
|
static void Generate_MyToken PARAMS(( CLIENT *Client ));
|
|
|
|
static void Adjust_Counters PARAMS(( CLIENT *Client ));
|
2002-12-23 00:29:09 +01:00
|
|
|
|
2006-03-11 02:37:31 +01:00
|
|
|
static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer,
|
2009-04-12 01:09:42 +02:00
|
|
|
CLIENT *TopServer, int Type, const char *ID,
|
|
|
|
const char *User, const char *Hostname, const char *Info,
|
|
|
|
int Hops, int Token, const char *Modes,
|
2008-08-16 17:19:27 +02:00
|
|
|
bool Idented));
|
|
|
|
|
2009-04-12 01:09:42 +02:00
|
|
|
static void Destroy_UserOrService PARAMS((CLIENT *Client,const char *Txt, const char *FwdMsg,
|
2008-08-16 17:19:27 +02:00
|
|
|
bool SendQuit));
|
2006-03-11 02:37:31 +01:00
|
|
|
|
2002-12-23 00:29:09 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
|
|
|
Client_Init( void )
|
2001-12-14 09:13:43 +01:00
|
|
|
{
|
2001-12-27 18:15:29 +01:00
|
|
|
struct hostent *h;
|
|
|
|
|
2001-12-14 09:13:43 +01:00
|
|
|
This_Server = New_Client_Struct( );
|
|
|
|
if( ! This_Server )
|
|
|
|
{
|
|
|
|
Log( LOG_EMERG, "Can't allocate client structure for server! Going down." );
|
2003-03-31 17:54:21 +02:00
|
|
|
Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
|
2001-12-14 09:13:43 +01:00
|
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Client-Struktur dieses Servers */
|
|
|
|
This_Server->next = NULL;
|
|
|
|
This_Server->type = CLIENT_SERVER;
|
|
|
|
This_Server->conn_id = NONE;
|
|
|
|
This_Server->introducer = This_Server;
|
2002-01-09 02:08:08 +01:00
|
|
|
This_Server->mytoken = 1;
|
2002-01-12 00:50:40 +01:00
|
|
|
This_Server->hops = 0;
|
2001-12-27 18:15:29 +01:00
|
|
|
|
2001-12-23 23:04:37 +01:00
|
|
|
gethostname( This_Server->host, CLIENT_HOST_LEN );
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
if (Conf_DNS) {
|
2007-10-25 13:01:19 +02:00
|
|
|
h = gethostbyname( This_Server->host );
|
|
|
|
if (h) strlcpy(This_Server->host, h->h_name, sizeof(This_Server->host));
|
|
|
|
}
|
2002-03-25 17:59:36 +01:00
|
|
|
Client_SetID( This_Server, Conf_ServerName );
|
|
|
|
Client_SetInfo( This_Server, Conf_ServerInfo );
|
2001-12-23 23:04:37 +01:00
|
|
|
|
2001-12-14 09:13:43 +01:00
|
|
|
My_Clients = This_Server;
|
2005-05-16 14:23:48 +02:00
|
|
|
|
|
|
|
memset( &My_Whowas, 0, sizeof( My_Whowas ));
|
2001-12-14 09:13:43 +01:00
|
|
|
} /* Client_Init */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
|
|
|
Client_Exit( void )
|
2001-12-14 09:13:43 +01:00
|
|
|
{
|
2001-12-23 23:04:37 +01:00
|
|
|
CLIENT *c, *next;
|
2005-03-19 19:43:48 +01:00
|
|
|
int cnt;
|
2001-12-23 23:04:37 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
if( NGIRCd_SignalRestart ) Client_Destroy( This_Server, "Server going down (restarting).", NULL, false );
|
|
|
|
else Client_Destroy( This_Server, "Server going down.", NULL, false );
|
2001-12-23 23:04:37 +01:00
|
|
|
|
|
|
|
cnt = 0;
|
|
|
|
c = My_Clients;
|
|
|
|
while( c )
|
|
|
|
{
|
|
|
|
cnt++;
|
2002-03-25 20:11:01 +01:00
|
|
|
next = (CLIENT *)c->next;
|
2001-12-23 23:04:37 +01:00
|
|
|
free( c );
|
|
|
|
c = next;
|
|
|
|
}
|
2001-12-25 23:04:26 +01:00
|
|
|
if( cnt ) Log( LOG_INFO, "Freed %d client structure%s.", cnt, cnt == 1 ? "" : "s" );
|
2002-01-06 16:18:14 +01:00
|
|
|
} /* Client_Exit */
|
2001-12-14 09:13:43 +01:00
|
|
|
|
|
|
|
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
2005-03-19 19:43:48 +01:00
|
|
|
Client_ThisServer( void )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
return This_Server;
|
|
|
|
} /* Client_ThisServer */
|
|
|
|
|
|
|
|
|
2006-03-11 02:37:31 +01:00
|
|
|
/**
|
|
|
|
* Initialize new local client; wrapper function for Init_New_Client().
|
|
|
|
* @return New CLIENT structure.
|
|
|
|
*/
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_NewLocal(CONN_ID Idx, const char *Hostname, int Type, bool Idented)
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2006-03-11 02:37:31 +01:00
|
|
|
return Init_New_Client(Idx, This_Server, NULL, Type, NULL, NULL,
|
|
|
|
Hostname, NULL, 0, 0, NULL, Idented);
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_NewLocal */
|
|
|
|
|
|
|
|
|
2006-03-11 02:37:31 +01:00
|
|
|
/**
|
|
|
|
* Initialize new remote server; wrapper function for Init_New_Client().
|
|
|
|
* @return New CLIENT structure.
|
|
|
|
*/
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_NewRemoteServer(CLIENT *Introducer, const char *Hostname, CLIENT *TopServer,
|
|
|
|
int Hops, int Token, const char *Info, bool Idented)
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2006-03-11 02:37:31 +01:00
|
|
|
return Init_New_Client(NONE, Introducer, TopServer, CLIENT_SERVER,
|
|
|
|
Hostname, NULL, Hostname, Info, Hops, Token, NULL, Idented);
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_NewRemoteServer */
|
|
|
|
|
|
|
|
|
2006-03-11 02:37:31 +01:00
|
|
|
/**
|
|
|
|
* Initialize new remote client; wrapper function for Init_New_Client().
|
|
|
|
* @return New CLIENT structure.
|
|
|
|
*/
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_NewRemoteUser(CLIENT *Introducer, const char *Nick, int Hops, const char *User,
|
|
|
|
const char *Hostname, int Token, const char *Modes, const char *Info, bool Idented)
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2006-03-11 02:37:31 +01:00
|
|
|
return Init_New_Client(NONE, Introducer, NULL, CLIENT_USER, Nick,
|
|
|
|
User, Hostname, Info, Hops, Token, Modes, Idented);
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_NewRemoteUser */
|
|
|
|
|
|
|
|
|
2006-03-11 02:37:31 +01:00
|
|
|
/**
|
|
|
|
* Initialize new client and set up the given parameters like client type,
|
|
|
|
* user name, host name, introducing server etc. ...
|
|
|
|
* @return New CLIENT structure.
|
|
|
|
*/
|
2006-03-10 21:25:29 +01:00
|
|
|
static CLIENT *
|
2006-03-11 02:37:31 +01:00
|
|
|
Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer,
|
2010-02-10 23:40:03 +01:00
|
|
|
int Type, const char *ID, const char *User, const char *Hostname,
|
|
|
|
const char *Info, int Hops, int Token, const char *Modes, bool Idented)
|
2001-12-23 23:04:37 +01:00
|
|
|
{
|
|
|
|
CLIENT *client;
|
|
|
|
|
2010-02-10 23:40:03 +01:00
|
|
|
assert(Idx >= NONE);
|
|
|
|
assert(Introducer != NULL);
|
|
|
|
assert(Hostname != NULL);
|
2002-01-04 02:21:22 +01:00
|
|
|
|
2010-02-10 23:40:03 +01:00
|
|
|
client = New_Client_Struct();
|
|
|
|
if (!client)
|
|
|
|
return NULL;
|
2001-12-23 23:04:37 +01:00
|
|
|
|
2005-06-12 18:18:49 +02:00
|
|
|
client->starttime = time(NULL);
|
2001-12-23 23:04:37 +01:00
|
|
|
client->conn_id = Idx;
|
2002-01-04 02:21:22 +01:00
|
|
|
client->introducer = Introducer;
|
2002-01-29 01:14:49 +01:00
|
|
|
client->topserver = TopServer;
|
2002-01-04 02:21:22 +01:00
|
|
|
client->type = Type;
|
2010-02-10 23:40:03 +01:00
|
|
|
if (ID)
|
|
|
|
Client_SetID(client, ID);
|
2010-07-11 17:03:43 +02:00
|
|
|
if (User) {
|
2010-02-10 23:40:03 +01:00
|
|
|
Client_SetUser(client, User, Idented);
|
2010-07-11 17:03:43 +02:00
|
|
|
Client_SetOrigUser(client, User);
|
|
|
|
}
|
2010-02-10 23:40:03 +01:00
|
|
|
if (Hostname)
|
|
|
|
Client_SetHostname(client, Hostname);
|
|
|
|
if (Info)
|
|
|
|
Client_SetInfo(client, Info);
|
2002-01-04 02:21:22 +01:00
|
|
|
client->hops = Hops;
|
|
|
|
client->token = Token;
|
2010-02-10 23:40:03 +01:00
|
|
|
if (Modes)
|
|
|
|
Client_SetModes(client, Modes);
|
|
|
|
if (Type == CLIENT_SERVER)
|
|
|
|
Generate_MyToken(client);
|
2001-12-23 23:04:37 +01:00
|
|
|
|
2010-02-10 23:40:03 +01:00
|
|
|
if (strchr(client->modes, 'a'))
|
|
|
|
strlcpy(client->away, DEFAULT_AWAY_MSG, sizeof(client->away));
|
2002-03-04 02:04:46 +01:00
|
|
|
|
2002-03-25 20:11:01 +01:00
|
|
|
client->next = (POINTER *)My_Clients;
|
2001-12-23 23:04:37 +01:00
|
|
|
My_Clients = client;
|
2002-01-04 02:21:22 +01:00
|
|
|
|
2010-02-10 23:40:03 +01:00
|
|
|
Adjust_Counters(client);
|
2002-12-23 00:29:09 +01:00
|
|
|
|
2001-12-23 23:04:37 +01:00
|
|
|
return client;
|
2006-03-11 02:37:31 +01:00
|
|
|
} /* Init_New_Client */
|
2001-12-23 23:04:37 +01:00
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool SendQuit )
|
2001-12-23 23:04:37 +01:00
|
|
|
{
|
2009-04-21 08:40:10 +02:00
|
|
|
/* remove a client */
|
2001-12-23 23:04:37 +01:00
|
|
|
|
|
|
|
CLIENT *last, *c;
|
2009-04-12 01:09:42 +02:00
|
|
|
char msg[LINE_LEN];
|
|
|
|
const char *txt;
|
2001-12-23 23:04:37 +01:00
|
|
|
|
2001-12-24 02:31:14 +01:00
|
|
|
assert( Client != NULL );
|
2002-01-04 18:57:08 +01:00
|
|
|
|
2002-01-06 16:18:14 +01:00
|
|
|
if( LogMsg ) txt = LogMsg;
|
|
|
|
else txt = FwdMsg;
|
|
|
|
if( ! txt ) txt = "Reason unknown.";
|
|
|
|
|
2009-04-21 08:40:10 +02:00
|
|
|
/* netsplit message */
|
2005-06-04 14:32:09 +02:00
|
|
|
if( Client->type == CLIENT_SERVER ) {
|
|
|
|
strlcpy(msg, This_Server->id, sizeof (msg));
|
|
|
|
strlcat(msg, " ", sizeof (msg));
|
|
|
|
strlcat(msg, Client->id, sizeof (msg));
|
|
|
|
}
|
2002-03-10 23:03:20 +01:00
|
|
|
|
2001-12-23 23:04:37 +01:00
|
|
|
last = NULL;
|
|
|
|
c = My_Clients;
|
|
|
|
while( c )
|
|
|
|
{
|
2002-01-04 18:57:08 +01:00
|
|
|
if(( Client->type == CLIENT_SERVER ) && ( c->introducer == Client ) && ( c != Client ))
|
|
|
|
{
|
2009-04-21 08:40:10 +02:00
|
|
|
/*
|
|
|
|
* The client that is about to be removed is a server,
|
|
|
|
* the client we are checking right now is a child of that
|
|
|
|
* server and thus has to be removed, too.
|
|
|
|
*
|
|
|
|
* Call Client_Destroy() recursively with the server as the
|
|
|
|
* new "object to be removed". This starts the cycle again, until
|
|
|
|
* all servers that are linked via the original server have been
|
|
|
|
* removed.
|
|
|
|
*/
|
2005-03-19 19:43:48 +01:00
|
|
|
Client_Destroy( c, NULL, msg, false );
|
2002-01-04 18:57:08 +01:00
|
|
|
last = NULL;
|
|
|
|
c = My_Clients;
|
|
|
|
continue;
|
|
|
|
}
|
2001-12-23 23:04:37 +01:00
|
|
|
if( c == Client )
|
|
|
|
{
|
2009-04-21 08:40:10 +02:00
|
|
|
/* found the client: remove it */
|
2001-12-23 23:04:37 +01:00
|
|
|
if( last ) last->next = c->next;
|
2002-03-25 20:11:01 +01:00
|
|
|
else My_Clients = (CLIENT *)c->next;
|
2001-12-27 20:13:47 +01:00
|
|
|
|
2008-08-16 17:19:27 +02:00
|
|
|
if(c->type == CLIENT_USER || c->type == CLIENT_SERVICE)
|
|
|
|
Destroy_UserOrService(c, txt, FwdMsg, SendQuit);
|
2002-01-06 16:18:14 +01:00
|
|
|
else if( c->type == CLIENT_SERVER )
|
|
|
|
{
|
2002-02-27 15:47:53 +01:00
|
|
|
if( c != This_Server )
|
|
|
|
{
|
2002-03-27 21:52:58 +01:00
|
|
|
if( c->conn_id != NONE ) Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
|
|
|
|
else Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered: %s", c->id, txt );
|
2002-02-27 15:47:53 +01:00
|
|
|
}
|
2002-01-09 02:08:08 +01:00
|
|
|
|
2009-04-21 08:40:10 +02:00
|
|
|
/* inform other servers */
|
2002-12-19 05:33:27 +01:00
|
|
|
if( ! NGIRCd_SignalQuit )
|
2002-01-09 02:08:08 +01:00
|
|
|
{
|
|
|
|
if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :%s", c->id, FwdMsg );
|
|
|
|
else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :", c->id );
|
|
|
|
}
|
2002-01-04 18:57:08 +01:00
|
|
|
}
|
2002-02-27 15:47:53 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if( c->conn_id != NONE )
|
|
|
|
{
|
|
|
|
if( c->id[0] ) Log( LOG_NOTICE, "Client \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
|
|
|
|
else Log( LOG_NOTICE, "Client unregistered (connection %d): %s", c->conn_id, txt );
|
2006-03-25 00:25:38 +01:00
|
|
|
} else {
|
|
|
|
Log(LOG_WARNING, "Unregistered unknown client \"%s\": %s",
|
|
|
|
c->id[0] ? c->id : "(No Nick)", txt );
|
2002-02-27 15:47:53 +01:00
|
|
|
}
|
|
|
|
}
|
2001-12-27 20:13:47 +01:00
|
|
|
|
2001-12-23 23:04:37 +01:00
|
|
|
free( c );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
last = c;
|
2002-03-25 20:11:01 +01:00
|
|
|
c = (CLIENT *)c->next;
|
2001-12-23 23:04:37 +01:00
|
|
|
}
|
|
|
|
} /* Client_Destroy */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_SetHostname( CLIENT *Client, const char *Hostname )
|
2001-12-29 21:18:18 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
2002-03-06 15:30:43 +01:00
|
|
|
assert( Hostname != NULL );
|
2006-12-07 23:24:14 +01:00
|
|
|
|
2011-03-19 16:58:29 +01:00
|
|
|
if (strlen(Conf_CloakHost)) {
|
|
|
|
strlcpy( Client->host, Conf_CloakHost, sizeof( Client->host ));
|
2011-02-14 16:16:07 +01:00
|
|
|
} else {
|
|
|
|
strlcpy( Client->host, Hostname, sizeof( Client->host ));
|
|
|
|
}
|
2001-12-29 21:18:18 +01:00
|
|
|
} /* Client_SetHostname */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_SetID( CLIENT *Client, const char *ID )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
2002-03-06 15:30:43 +01:00
|
|
|
assert( ID != NULL );
|
|
|
|
|
2002-12-26 17:25:43 +01:00
|
|
|
strlcpy( Client->id, ID, sizeof( Client->id ));
|
2002-03-25 17:59:36 +01:00
|
|
|
|
2011-06-19 06:08:33 +02:00
|
|
|
if (Conf_CloakUserToNick) {
|
2010-12-20 03:35:17 +01:00
|
|
|
strlcpy( Client->user, ID, sizeof( Client->user ));
|
2011-06-19 06:08:33 +02:00
|
|
|
strlcpy( Client->info, ID, sizeof( Client->info ));
|
|
|
|
}
|
2010-12-20 03:35:17 +01:00
|
|
|
|
2002-03-25 17:59:36 +01:00
|
|
|
/* Hash */
|
|
|
|
Client->hash = Hash( Client->id );
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_SetID */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_SetUser( CLIENT *Client, const char *User, bool Idented )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2009-04-20 08:34:09 +02:00
|
|
|
/* set clients username */
|
2002-01-04 02:21:22 +01:00
|
|
|
|
|
|
|
assert( Client != NULL );
|
2002-03-06 15:30:43 +01:00
|
|
|
assert( User != NULL );
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2011-06-19 06:08:33 +02:00
|
|
|
if (Conf_CloakUserToNick) {
|
|
|
|
strlcpy(Client->user, Client->id, sizeof(Client->user));
|
|
|
|
} else if (Idented) {
|
2009-04-20 08:34:09 +02:00
|
|
|
strlcpy(Client->user, User, sizeof(Client->user));
|
|
|
|
} else {
|
2002-01-06 00:26:05 +01:00
|
|
|
Client->user[0] = '~';
|
2009-04-20 08:34:09 +02:00
|
|
|
strlcpy(Client->user + 1, User, sizeof(Client->user) - 1);
|
2002-01-06 00:26:05 +01:00
|
|
|
}
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_SetUser */
|
|
|
|
|
|
|
|
|
2010-07-11 17:03:43 +02:00
|
|
|
/**
|
|
|
|
* Set "original" user name of a client.
|
|
|
|
* This function saves the "original" user name, the user name specified by
|
|
|
|
* the peer using the USER command, into the CLIENT structure. This user
|
|
|
|
* name may be used for authentication, for example.
|
|
|
|
* @param Client The client.
|
|
|
|
* @param User User name to set.
|
|
|
|
*/
|
|
|
|
GLOBAL void
|
2010-10-24 21:48:32 +02:00
|
|
|
Client_SetOrigUser(CLIENT UNUSED *Client, const char UNUSED *User)
|
|
|
|
{
|
2010-07-11 17:03:43 +02:00
|
|
|
assert(Client != NULL);
|
|
|
|
assert(User != NULL);
|
|
|
|
|
2010-07-12 13:22:48 +02:00
|
|
|
#if defined(PAM) && defined(IDENTAUTH)
|
2010-07-11 17:03:43 +02:00
|
|
|
strlcpy(Client->orig_user, User, sizeof(Client->orig_user));
|
|
|
|
#endif
|
|
|
|
} /* Client_SetOrigUser */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_SetInfo( CLIENT *Client, const char *Info )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2009-04-20 08:34:09 +02:00
|
|
|
/* set client hostname */
|
2002-01-04 02:21:22 +01:00
|
|
|
|
|
|
|
assert( Client != NULL );
|
2002-03-06 15:30:43 +01:00
|
|
|
assert( Info != NULL );
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2011-06-19 06:08:33 +02:00
|
|
|
if (Conf_CloakUserToNick)
|
|
|
|
strlcpy(Client->info, Client->id, sizeof(Client->info));
|
|
|
|
else
|
|
|
|
strlcpy(Client->info, Info, sizeof(Client->info));
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_SetInfo */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_SetModes( CLIENT *Client, const char *Modes )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
2002-03-06 15:30:43 +01:00
|
|
|
assert( Modes != NULL );
|
|
|
|
|
2009-04-20 08:34:09 +02:00
|
|
|
strlcpy(Client->modes, Modes, sizeof( Client->modes ));
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_SetModes */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_SetFlags( CLIENT *Client, const char *Flags )
|
2002-09-03 20:54:31 +02:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
assert( Flags != NULL );
|
|
|
|
|
2009-04-20 08:34:09 +02:00
|
|
|
strlcpy(Client->flags, Flags, sizeof(Client->flags));
|
2002-09-03 20:54:31 +02:00
|
|
|
} /* Client_SetFlags */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_SetPassword( CLIENT *Client, const char *Pwd )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2009-04-20 08:34:09 +02:00
|
|
|
/* set password sent by client */
|
2002-01-04 02:21:22 +01:00
|
|
|
|
|
|
|
assert( Client != NULL );
|
2002-03-06 15:30:43 +01:00
|
|
|
assert( Pwd != NULL );
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2009-04-20 08:34:09 +02:00
|
|
|
strlcpy(Client->pwd, Pwd, sizeof(Client->pwd));
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_SetPassword */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2009-04-12 01:09:42 +02:00
|
|
|
Client_SetAway( CLIENT *Client, const char *Txt )
|
2002-02-27 19:22:09 +01:00
|
|
|
{
|
2003-01-08 23:03:21 +01:00
|
|
|
/* Set AWAY reason of client */
|
2002-02-27 19:22:09 +01:00
|
|
|
|
|
|
|
assert( Client != NULL );
|
2003-01-08 23:03:21 +01:00
|
|
|
assert( Txt != NULL );
|
2002-02-27 19:22:09 +01:00
|
|
|
|
2003-01-08 23:03:21 +01:00
|
|
|
strlcpy( Client->away, Txt, sizeof( Client->away ));
|
2008-08-16 17:52:02 +02:00
|
|
|
LogDebug("%s \"%s\" is away: %s", Client_TypeText(Client),
|
|
|
|
Client_Mask(Client), Txt);
|
2002-02-27 19:22:09 +01:00
|
|
|
} /* Client_SetAway */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
|
|
|
Client_SetType( CLIENT *Client, int Type )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
Client->type = Type;
|
2002-01-08 00:42:12 +01:00
|
|
|
if( Type == CLIENT_SERVER ) Generate_MyToken( Client );
|
2002-12-23 00:29:09 +01:00
|
|
|
Adjust_Counters( Client );
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_SetType */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
|
|
|
Client_SetHops( CLIENT *Client, int Hops )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
Client->hops = Hops;
|
|
|
|
} /* Client_SetHops */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
|
|
|
Client_SetToken( CLIENT *Client, int Token )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
Client->token = Token;
|
|
|
|
} /* Client_SetToken */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_SetIntroducer( CLIENT *Client, CLIENT *Introducer )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
2002-03-06 15:30:43 +01:00
|
|
|
assert( Introducer != NULL );
|
2002-01-04 02:21:22 +01:00
|
|
|
Client->introducer = Introducer;
|
|
|
|
} /* Client_SetIntroducer */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
|
|
|
Client_SetOperByMe( CLIENT *Client, bool OperByMe )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
Client->oper_by_me = OperByMe;
|
|
|
|
} /* Client_SetOperByMe */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
|
|
|
Client_ModeAdd( CLIENT *Client, char Mode )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2005-03-19 19:43:48 +01:00
|
|
|
/* Set Mode.
|
|
|
|
* If Client already alread had Mode, return false.
|
|
|
|
* If the Mode was newly set, return true.
|
|
|
|
*/
|
2002-01-04 02:21:22 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
char x[2];
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2002-01-04 02:21:22 +01:00
|
|
|
assert( Client != NULL );
|
|
|
|
|
|
|
|
x[0] = Mode; x[1] = '\0';
|
2009-04-20 08:34:09 +02:00
|
|
|
if (!strchr( Client->modes, x[0])) {
|
2002-12-26 17:48:14 +01:00
|
|
|
strlcat( Client->modes, x, sizeof( Client->modes ));
|
2005-03-19 19:43:48 +01:00
|
|
|
return true;
|
2002-01-04 02:21:22 +01:00
|
|
|
}
|
2005-03-19 19:43:48 +01:00
|
|
|
else return false;
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_ModeAdd */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
|
|
|
Client_ModeDel( CLIENT *Client, char Mode )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2005-03-19 19:43:48 +01:00
|
|
|
/* Delete Mode.
|
|
|
|
* If Mode was removed, return true.
|
|
|
|
* If Client did not have Mode, return false.
|
|
|
|
*/
|
2002-01-04 02:21:22 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
char x[2], *p;
|
2002-01-04 02:21:22 +01:00
|
|
|
|
|
|
|
assert( Client != NULL );
|
|
|
|
|
|
|
|
x[0] = Mode; x[1] = '\0';
|
|
|
|
|
|
|
|
p = strchr( Client->modes, x[0] );
|
2005-03-19 19:43:48 +01:00
|
|
|
if( ! p ) return false;
|
2002-01-04 02:21:22 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
/* Client has Mode -> delete */
|
2002-01-04 02:21:22 +01:00
|
|
|
while( *p )
|
|
|
|
{
|
|
|
|
*p = *(p + 1);
|
|
|
|
p++;
|
|
|
|
}
|
2005-03-19 19:43:48 +01:00
|
|
|
return true;
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_ModeDel */
|
|
|
|
|
|
|
|
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
2008-05-03 21:20:02 +02:00
|
|
|
Client_Search( const char *Nick )
|
2001-12-31 03:18:51 +01:00
|
|
|
{
|
2005-03-19 19:43:48 +01:00
|
|
|
/* return Client-Structure that has the corresponding Nick.
|
|
|
|
* If none is found, return NULL.
|
|
|
|
*/
|
2001-12-31 03:18:51 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
char search_id[CLIENT_ID_LEN], *ptr;
|
2002-01-27 23:07:36 +01:00
|
|
|
CLIENT *c = NULL;
|
2002-03-25 17:59:36 +01:00
|
|
|
UINT32 search_hash;
|
2001-12-31 03:18:51 +01:00
|
|
|
|
|
|
|
assert( Nick != NULL );
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
/* copy Nick and truncate hostmask if necessary */
|
2002-12-26 17:25:43 +01:00
|
|
|
strlcpy( search_id, Nick, sizeof( search_id ));
|
2002-03-25 17:59:36 +01:00
|
|
|
ptr = strchr( search_id, '!' );
|
2002-01-27 19:27:12 +01:00
|
|
|
if( ptr ) *ptr = '\0';
|
|
|
|
|
2009-04-20 08:34:09 +02:00
|
|
|
search_hash = Hash(search_id);
|
2002-03-25 17:59:36 +01:00
|
|
|
|
2001-12-31 03:18:51 +01:00
|
|
|
c = My_Clients;
|
2009-04-20 08:34:09 +02:00
|
|
|
while (c) {
|
|
|
|
if (c->hash == search_hash && strcasecmp(c->id, search_id) == 0)
|
|
|
|
return c;
|
2002-03-25 20:11:01 +01:00
|
|
|
c = (CLIENT *)c->next;
|
2002-01-04 02:21:22 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
2002-03-25 17:59:36 +01:00
|
|
|
} /* Client_Search */
|
2002-01-04 02:21:22 +01:00
|
|
|
|
|
|
|
|
2010-12-24 12:48:03 +01:00
|
|
|
/**
|
|
|
|
* Get client structure ("introducer") identfied by a server token.
|
|
|
|
* @return CLIENT structure or NULL if none could be found.
|
|
|
|
*/
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
2005-03-19 19:43:48 +01:00
|
|
|
Client_GetFromToken( CLIENT *Client, int Token )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
CLIENT *c;
|
|
|
|
|
|
|
|
assert( Client != NULL );
|
2010-12-24 12:48:03 +01:00
|
|
|
|
|
|
|
if (!Token)
|
|
|
|
return NULL;
|
2002-01-04 02:21:22 +01:00
|
|
|
|
|
|
|
c = My_Clients;
|
2009-04-20 08:34:09 +02:00
|
|
|
while (c) {
|
|
|
|
if ((c->type == CLIENT_SERVER) && (c->introducer == Client) &&
|
|
|
|
(c->token == Token))
|
|
|
|
return c;
|
2002-03-25 20:11:01 +01:00
|
|
|
c = (CLIENT *)c->next;
|
2001-12-31 03:18:51 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_GetFromToken */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL int
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_Type( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->type;
|
|
|
|
} /* Client_Type */
|
|
|
|
|
|
|
|
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CONN_ID
|
|
|
|
Client_Conn( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->conn_id;
|
|
|
|
} /* Client_Conn */
|
2001-12-31 03:18:51 +01:00
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_ID( CLIENT *Client )
|
2001-12-26 04:19:16 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
|
2002-03-06 15:30:43 +01:00
|
|
|
#ifdef DEBUG
|
2007-11-21 13:16:33 +01:00
|
|
|
if(Client->type == CLIENT_USER)
|
|
|
|
assert(strlen(Client->id) < Conf_MaxNickLength);
|
2002-03-06 15:30:43 +01:00
|
|
|
#endif
|
|
|
|
|
2002-01-04 02:21:22 +01:00
|
|
|
if( Client->id[0] ) return Client->id;
|
2001-12-26 04:19:16 +01:00
|
|
|
else return "*";
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_ID */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_Info( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->info;
|
|
|
|
} /* Client_Info */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_User( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
2006-12-07 23:24:14 +01:00
|
|
|
return Client->user[0] ? Client->user : "~";
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_User */
|
|
|
|
|
|
|
|
|
2010-07-11 17:03:43 +02:00
|
|
|
#ifdef PAM
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the "original" user name as supplied by the USER command.
|
|
|
|
* The user name as given by the client is used for authentication instead
|
|
|
|
* of the one detected using IDENT requests.
|
|
|
|
* @param Client The client.
|
|
|
|
* @return Original user name.
|
|
|
|
*/
|
|
|
|
GLOBAL char *
|
|
|
|
Client_OrigUser(CLIENT *Client) {
|
|
|
|
#ifndef IDENTAUTH
|
|
|
|
char *user = Client->user;
|
|
|
|
|
|
|
|
if (user[0] == '~')
|
|
|
|
user++;
|
|
|
|
return user;
|
|
|
|
#else
|
|
|
|
return Client->orig_user;
|
|
|
|
#endif
|
|
|
|
} /* Client_OrigUser */
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2010-08-17 20:51:14 +02:00
|
|
|
/**
|
|
|
|
* Return the hostname of a client.
|
|
|
|
* @param Client Pointer to client structure
|
|
|
|
* @return Pointer to client hostname
|
|
|
|
*/
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2010-08-17 20:51:14 +02:00
|
|
|
Client_Hostname(CLIENT *Client)
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2010-08-17 20:51:14 +02:00
|
|
|
assert (Client != NULL);
|
2002-01-04 02:21:22 +01:00
|
|
|
return Client->host;
|
|
|
|
} /* Client_Hostname */
|
|
|
|
|
|
|
|
|
2010-08-17 20:54:33 +02:00
|
|
|
/**
|
|
|
|
* Get potentially cloaked hostname of a client.
|
|
|
|
* If the client has not enabled cloaking, the real hostname is used.
|
|
|
|
* @param Client Pointer to client structure
|
|
|
|
* @return Pointer to client hostname
|
|
|
|
*/
|
|
|
|
GLOBAL char *
|
|
|
|
Client_HostnameCloaked(CLIENT *Client)
|
|
|
|
{
|
|
|
|
assert(Client != NULL);
|
|
|
|
if (Client_HasMode(Client, 'x'))
|
|
|
|
return Client_ID(Client->introducer);
|
|
|
|
else
|
|
|
|
return Client_Hostname(Client);
|
|
|
|
} /* Client_HostnameCloaked */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_Password( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->pwd;
|
|
|
|
} /* Client_Password */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_Modes( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->modes;
|
|
|
|
} /* Client_Modes */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2002-09-03 20:54:31 +02:00
|
|
|
Client_Flags( CLIENT *Client )
|
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->flags;
|
|
|
|
} /* Client_Flags */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_OperByMe( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->oper_by_me;
|
|
|
|
} /* Client_OperByMe */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL int
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_Hops( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->hops;
|
|
|
|
} /* Client_Hops */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL int
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_Token( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->token;
|
|
|
|
} /* Client_Token */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL int
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_MyToken( CLIENT *Client )
|
2002-01-08 00:42:12 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->mytoken;
|
|
|
|
} /* Client_MyToken */
|
|
|
|
|
|
|
|
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
|
|
|
Client_NextHop( CLIENT *Client )
|
2002-01-05 21:08:17 +01:00
|
|
|
{
|
|
|
|
CLIENT *c;
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2002-01-05 21:08:17 +01:00
|
|
|
assert( Client != NULL );
|
|
|
|
|
|
|
|
c = Client;
|
2006-10-07 12:40:52 +02:00
|
|
|
while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server ))
|
|
|
|
c = c->introducer;
|
|
|
|
|
2002-01-05 21:08:17 +01:00
|
|
|
return c;
|
|
|
|
} /* Client_NextHop */
|
|
|
|
|
|
|
|
|
2009-04-20 08:34:09 +02:00
|
|
|
/**
|
2010-08-17 20:51:14 +02:00
|
|
|
* Return ID of a client: "client!user@host"
|
|
|
|
* This client ID is used for IRC prefixes, for example.
|
|
|
|
* Please note that this function uses a global static buffer, so you can't
|
2011-12-30 00:50:27 +01:00
|
|
|
* nest invocations without overwriting earlier results!
|
2010-08-17 20:51:14 +02:00
|
|
|
* @param Client Pointer to client structure
|
|
|
|
* @return Pointer to global buffer containing the client ID
|
2009-04-20 08:34:09 +02:00
|
|
|
*/
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_Mask( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
2010-08-17 20:51:14 +02:00
|
|
|
static char Mask_Buffer[GETID_LEN];
|
2002-01-04 02:21:22 +01:00
|
|
|
|
2010-08-17 20:51:14 +02:00
|
|
|
assert (Client != NULL);
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2010-08-17 20:51:14 +02:00
|
|
|
/* Servers: return name only, there is no "mask" */
|
|
|
|
if (Client->type == CLIENT_SERVER)
|
|
|
|
return Client->id;
|
2002-01-04 02:21:22 +01:00
|
|
|
|
2010-08-17 20:51:14 +02:00
|
|
|
snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s",
|
|
|
|
Client->id, Client->user, Client->host);
|
|
|
|
return Mask_Buffer;
|
2002-01-04 02:21:22 +01:00
|
|
|
} /* Client_Mask */
|
|
|
|
|
|
|
|
|
2010-08-17 20:54:33 +02:00
|
|
|
/**
|
|
|
|
* Return ID of a client with cloaked hostname: "client!user@server-name"
|
|
|
|
* This client ID is used for IRC prefixes, for example.
|
|
|
|
* Please note that this function uses a global static buffer, so you can't
|
2011-12-30 00:50:27 +01:00
|
|
|
* nest invocations without overwriting earlier results!
|
2010-08-17 20:54:33 +02:00
|
|
|
* If the client has not enabled cloaking, the real hostname is used.
|
|
|
|
* @param Client Pointer to client structure
|
|
|
|
* @return Pointer to global buffer containing the client ID
|
|
|
|
*/
|
|
|
|
GLOBAL char *
|
|
|
|
Client_MaskCloaked(CLIENT *Client)
|
|
|
|
{
|
|
|
|
static char Mask_Buffer[GETID_LEN];
|
|
|
|
|
|
|
|
assert (Client != NULL);
|
|
|
|
|
|
|
|
/* Is the client using cloaking at all? */
|
|
|
|
if (!Client_HasMode(Client, 'x'))
|
|
|
|
return Client_Mask(Client);
|
|
|
|
|
|
|
|
snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s",
|
|
|
|
Client->id, Client->user, Client_ID(Client->introducer));
|
|
|
|
return Mask_Buffer;
|
|
|
|
} /* Client_MaskCloaked */
|
|
|
|
|
|
|
|
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
|
|
|
Client_Introducer( CLIENT *Client )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->introducer;
|
|
|
|
} /* Client_Introducer */
|
|
|
|
|
|
|
|
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
|
|
|
Client_TopServer( CLIENT *Client )
|
2002-01-29 01:14:49 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->topserver;
|
|
|
|
} /* Client_TopServer */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
|
|
|
Client_HasMode( CLIENT *Client, char Mode )
|
2002-01-04 02:21:22 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return strchr( Client->modes, Mode ) != NULL;
|
|
|
|
} /* Client_HasMode */
|
2001-12-26 04:19:16 +01:00
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL char *
|
2002-05-27 15:09:26 +02:00
|
|
|
Client_Away( CLIENT *Client )
|
2002-02-27 19:22:09 +01:00
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->away;
|
|
|
|
} /* Client_Away */
|
|
|
|
|
|
|
|
|
2011-08-19 10:44:26 +02:00
|
|
|
/**
|
|
|
|
* Make sure that a given nickname is valid.
|
|
|
|
*
|
|
|
|
* If the nickname is not valid for the given client, this function sends back
|
|
|
|
* the appropriate error messages.
|
|
|
|
*
|
|
|
|
* @param Client Client that wants to change the nickname.
|
|
|
|
* @param Nick New nick name.
|
|
|
|
* @returns true if nickname is valid, false otherwise.
|
|
|
|
*/
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
2011-08-19 10:44:26 +02:00
|
|
|
Client_CheckNick(CLIENT *Client, char *Nick)
|
2001-12-26 15:45:37 +01:00
|
|
|
{
|
2011-08-19 10:44:26 +02:00
|
|
|
assert(Client != NULL);
|
|
|
|
assert(Nick != NULL);
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2011-08-19 10:44:26 +02:00
|
|
|
if (!Client_IsValidNick(Nick)) {
|
2011-08-19 11:09:40 +02:00
|
|
|
if (strlen(Nick ) >= Conf_MaxNickLength)
|
|
|
|
IRC_WriteStrClient(Client, ERR_NICKNAMETOOLONG_MSG,
|
|
|
|
Client_ID(Client), Nick,
|
|
|
|
Conf_MaxNickLength - 1);
|
|
|
|
else
|
|
|
|
IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
|
|
|
|
Client_ID(Client), Nick);
|
2005-03-19 19:43:48 +01:00
|
|
|
return false;
|
2002-02-17 20:02:49 +01:00
|
|
|
}
|
2001-12-26 15:45:37 +01:00
|
|
|
|
2011-08-19 10:44:26 +02:00
|
|
|
/* Nickname already registered? */
|
|
|
|
if (Client_Search(Nick)) {
|
|
|
|
IRC_WriteStrClient(Client, ERR_NICKNAMEINUSE_MSG,
|
|
|
|
Client_ID(Client), Nick);
|
2005-03-19 19:43:48 +01:00
|
|
|
return false;
|
2001-12-26 15:45:37 +01:00
|
|
|
}
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
return true;
|
2001-12-26 15:45:37 +01:00
|
|
|
} /* Client_CheckNick */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
|
|
|
Client_CheckID( CLIENT *Client, char *ID )
|
2002-01-03 03:28:06 +01:00
|
|
|
{
|
2005-03-19 19:43:48 +01:00
|
|
|
char str[COMMAND_LEN];
|
2002-01-03 03:28:06 +01:00
|
|
|
CLIENT *c;
|
|
|
|
|
|
|
|
assert( Client != NULL );
|
|
|
|
assert( Client->conn_id > NONE );
|
|
|
|
assert( ID != NULL );
|
|
|
|
|
2009-07-17 16:16:04 +02:00
|
|
|
/* ID too long? */
|
2009-04-20 08:34:09 +02:00
|
|
|
if (strlen(ID) > CLIENT_ID_LEN) {
|
|
|
|
IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID(Client), ID);
|
2005-03-19 19:43:48 +01:00
|
|
|
return false;
|
2002-02-17 20:02:49 +01:00
|
|
|
}
|
2002-01-03 03:28:06 +01:00
|
|
|
|
2009-07-17 16:16:04 +02:00
|
|
|
/* ID already in use? */
|
2002-01-03 03:28:06 +01:00
|
|
|
c = My_Clients;
|
2009-04-20 08:34:09 +02:00
|
|
|
while (c) {
|
|
|
|
if (strcasecmp(c->id, ID) == 0) {
|
|
|
|
snprintf(str, sizeof(str), "ID \"%s\" already registered", ID);
|
2009-07-17 16:16:04 +02:00
|
|
|
if (c->conn_id != NONE)
|
2009-04-20 08:34:09 +02:00
|
|
|
Log(LOG_ERR, "%s (on connection %d)!", str, c->conn_id);
|
|
|
|
else
|
|
|
|
Log(LOG_ERR, "%s (via network)!", str);
|
|
|
|
Conn_Close(Client->conn_id, str, str, true);
|
2005-03-19 19:43:48 +01:00
|
|
|
return false;
|
2002-01-03 03:28:06 +01:00
|
|
|
}
|
2002-03-25 20:11:01 +01:00
|
|
|
c = (CLIENT *)c->next;
|
2002-01-03 03:28:06 +01:00
|
|
|
}
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
return true;
|
2002-01-03 03:28:06 +01:00
|
|
|
} /* Client_CheckID */
|
|
|
|
|
|
|
|
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
2005-03-19 19:43:48 +01:00
|
|
|
Client_First( void )
|
2001-12-31 16:33:13 +01:00
|
|
|
{
|
|
|
|
return My_Clients;
|
|
|
|
} /* Client_First */
|
|
|
|
|
|
|
|
|
2002-05-27 15:09:26 +02:00
|
|
|
GLOBAL CLIENT *
|
|
|
|
Client_Next( CLIENT *c )
|
2001-12-31 16:33:13 +01:00
|
|
|
{
|
|
|
|
assert( c != NULL );
|
2002-03-25 20:11:01 +01:00
|
|
|
return (CLIENT *)c->next;
|
2001-12-31 16:33:13 +01:00
|
|
|
} /* Client_Next */
|
2002-01-16 23:10:35 +01:00
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL long
|
|
|
|
Client_UserCount( void )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
return Count( CLIENT_USER );
|
|
|
|
} /* Client_UserCount */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL long
|
|
|
|
Client_ServiceCount( void )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
return Count( CLIENT_SERVICE );;
|
|
|
|
} /* Client_ServiceCount */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL long
|
|
|
|
Client_ServerCount( void )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
return Count( CLIENT_SERVER );
|
|
|
|
} /* Client_ServerCount */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL long
|
|
|
|
Client_MyUserCount( void )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
return MyCount( CLIENT_USER );
|
|
|
|
} /* Client_MyUserCount */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL long
|
|
|
|
Client_MyServiceCount( void )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
return MyCount( CLIENT_SERVICE );
|
|
|
|
} /* Client_MyServiceCount */
|
|
|
|
|
|
|
|
|
2006-10-07 12:40:52 +02:00
|
|
|
GLOBAL unsigned long
|
2005-03-19 19:43:48 +01:00
|
|
|
Client_MyServerCount( void )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
2002-04-14 15:54:51 +02:00
|
|
|
CLIENT *c;
|
2006-12-07 23:24:14 +01:00
|
|
|
unsigned long cnt = 0;
|
2002-04-14 15:54:51 +02:00
|
|
|
|
|
|
|
c = My_Clients;
|
|
|
|
while( c )
|
|
|
|
{
|
|
|
|
if(( c->type == CLIENT_SERVER ) && ( c->hops == 1 )) cnt++;
|
|
|
|
c = (CLIENT *)c->next;
|
|
|
|
}
|
|
|
|
return cnt;
|
2002-01-16 23:10:35 +01:00
|
|
|
} /* Client_MyServerCount */
|
|
|
|
|
|
|
|
|
2006-10-07 12:40:52 +02:00
|
|
|
GLOBAL unsigned long
|
2005-03-19 19:43:48 +01:00
|
|
|
Client_OperCount( void )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
CLIENT *c;
|
2006-12-07 23:24:14 +01:00
|
|
|
unsigned long cnt = 0;
|
2002-01-16 23:10:35 +01:00
|
|
|
|
|
|
|
c = My_Clients;
|
|
|
|
while( c )
|
|
|
|
{
|
|
|
|
if( c && ( c->type == CLIENT_USER ) && ( strchr( c->modes, 'o' ))) cnt++;
|
2002-03-25 20:11:01 +01:00
|
|
|
c = (CLIENT *)c->next;
|
2002-01-16 23:10:35 +01:00
|
|
|
}
|
|
|
|
return cnt;
|
|
|
|
} /* Client_OperCount */
|
|
|
|
|
|
|
|
|
2006-10-07 12:40:52 +02:00
|
|
|
GLOBAL unsigned long
|
2005-03-19 19:43:48 +01:00
|
|
|
Client_UnknownCount( void )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
CLIENT *c;
|
2006-10-07 12:40:52 +02:00
|
|
|
unsigned long cnt = 0;
|
2002-01-16 23:10:35 +01:00
|
|
|
|
|
|
|
c = My_Clients;
|
|
|
|
while( c )
|
|
|
|
{
|
|
|
|
if( c && ( c->type != CLIENT_USER ) && ( c->type != CLIENT_SERVICE ) && ( c->type != CLIENT_SERVER )) cnt++;
|
2002-03-25 20:11:01 +01:00
|
|
|
c = (CLIENT *)c->next;
|
2002-01-16 23:10:35 +01:00
|
|
|
}
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2002-01-16 23:10:35 +01:00
|
|
|
return cnt;
|
|
|
|
} /* Client_UnknownCount */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL long
|
|
|
|
Client_MaxUserCount( void )
|
2002-12-23 00:29:09 +01:00
|
|
|
{
|
|
|
|
return Max_Users;
|
|
|
|
} /* Client_MaxUserCount */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL long
|
|
|
|
Client_MyMaxUserCount( void )
|
2002-12-23 00:29:09 +01:00
|
|
|
{
|
|
|
|
return My_Max_Users;
|
|
|
|
} /* Client_MyMaxUserCount */
|
|
|
|
|
|
|
|
|
2011-08-19 10:44:26 +02:00
|
|
|
/**
|
|
|
|
* Check that a given nickname is valid.
|
|
|
|
*
|
|
|
|
* @param Nick the nickname to check.
|
|
|
|
* @returns true if nickname is valid, false otherwise.
|
|
|
|
*/
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
2011-08-19 10:44:26 +02:00
|
|
|
Client_IsValidNick(const char *Nick)
|
2002-02-06 17:49:41 +01:00
|
|
|
{
|
2006-10-06 21:57:56 +02:00
|
|
|
const char *ptr;
|
|
|
|
static const char goodchars[] = ";0123456789-";
|
2002-03-02 02:35:50 +01:00
|
|
|
|
2011-08-19 10:44:26 +02:00
|
|
|
assert (Nick != NULL);
|
2002-02-06 17:49:41 +01:00
|
|
|
|
2011-08-19 10:44:26 +02:00
|
|
|
if (strchr(goodchars, Nick[0]))
|
|
|
|
return false;
|
|
|
|
if (strlen(Nick ) >= Conf_MaxNickLength)
|
|
|
|
return false;
|
2002-03-02 02:35:50 +01:00
|
|
|
|
|
|
|
ptr = Nick;
|
2011-08-19 10:44:26 +02:00
|
|
|
while (*ptr) {
|
|
|
|
if (*ptr < 'A' && !strchr(goodchars, *ptr ))
|
|
|
|
return false;
|
|
|
|
if (*ptr > '}')
|
|
|
|
return false;
|
2002-03-02 02:35:50 +01:00
|
|
|
ptr++;
|
|
|
|
}
|
2006-10-06 21:57:56 +02:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
return true;
|
2002-02-06 17:49:41 +01:00
|
|
|
} /* Client_IsValidNick */
|
|
|
|
|
|
|
|
|
2005-05-16 14:23:48 +02:00
|
|
|
/**
|
|
|
|
* Return pointer to "My_Whowas" structure.
|
|
|
|
*/
|
|
|
|
GLOBAL WHOWAS *
|
|
|
|
Client_GetWhowas( void )
|
|
|
|
{
|
|
|
|
return My_Whowas;
|
|
|
|
} /* Client_GetWhowas */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the index of the last used WHOWAS entry.
|
|
|
|
*/
|
|
|
|
GLOBAL int
|
|
|
|
Client_GetLastWhowasIndex( void )
|
|
|
|
{
|
|
|
|
return Last_Whowas;
|
|
|
|
} /* Client_GetLastWhowasIndex */
|
|
|
|
|
|
|
|
|
2005-06-12 18:18:49 +02:00
|
|
|
/**
|
|
|
|
* Get the start time of this client.
|
|
|
|
* The result is the start time in seconds since 1970-01-01, as reported
|
|
|
|
* by the C function time(NULL).
|
|
|
|
*/
|
|
|
|
GLOBAL time_t
|
|
|
|
Client_StartTime(CLIENT *Client)
|
|
|
|
{
|
|
|
|
assert( Client != NULL );
|
|
|
|
return Client->starttime;
|
|
|
|
} /* Client_Uptime */
|
|
|
|
|
|
|
|
|
2006-10-07 12:40:52 +02:00
|
|
|
static unsigned long
|
2002-05-27 15:09:26 +02:00
|
|
|
Count( CLIENT_TYPE Type )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
CLIENT *c;
|
2006-10-07 12:40:52 +02:00
|
|
|
unsigned long cnt = 0;
|
2002-01-16 23:10:35 +01:00
|
|
|
|
|
|
|
c = My_Clients;
|
|
|
|
while( c )
|
|
|
|
{
|
2002-04-14 15:54:51 +02:00
|
|
|
if( c->type == Type ) cnt++;
|
2002-03-25 20:11:01 +01:00
|
|
|
c = (CLIENT *)c->next;
|
2002-01-16 23:10:35 +01:00
|
|
|
}
|
|
|
|
return cnt;
|
|
|
|
} /* Count */
|
|
|
|
|
|
|
|
|
2006-10-07 12:40:52 +02:00
|
|
|
static unsigned long
|
2002-05-27 15:09:26 +02:00
|
|
|
MyCount( CLIENT_TYPE Type )
|
2002-01-16 23:10:35 +01:00
|
|
|
{
|
|
|
|
CLIENT *c;
|
2006-10-07 12:40:52 +02:00
|
|
|
unsigned long cnt = 0;
|
2002-01-16 23:10:35 +01:00
|
|
|
|
|
|
|
c = My_Clients;
|
|
|
|
while( c )
|
|
|
|
{
|
2002-04-14 15:54:51 +02:00
|
|
|
if(( c->introducer == This_Server ) && ( c->type == Type )) cnt++;
|
2002-03-25 20:11:01 +01:00
|
|
|
c = (CLIENT *)c->next;
|
2002-01-16 23:10:35 +01:00
|
|
|
}
|
|
|
|
return cnt;
|
|
|
|
} /* MyCount */
|
2001-12-31 16:33:13 +01:00
|
|
|
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static CLIENT *
|
2005-03-19 19:43:48 +01:00
|
|
|
New_Client_Struct( void )
|
2001-12-14 09:13:43 +01:00
|
|
|
{
|
2001-12-23 23:04:37 +01:00
|
|
|
/* Neue CLIENT-Struktur pre-initialisieren */
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2001-12-14 09:13:43 +01:00
|
|
|
CLIENT *c;
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2004-03-11 23:16:31 +01:00
|
|
|
c = (CLIENT *)malloc( sizeof( CLIENT ));
|
2001-12-14 09:13:43 +01:00
|
|
|
if( ! c )
|
|
|
|
{
|
2002-06-10 23:09:39 +02:00
|
|
|
Log( LOG_EMERG, "Can't allocate memory! [New_Client_Struct]" );
|
2001-12-14 09:13:43 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-01-20 01:11:49 +01:00
|
|
|
memset( c, 0, sizeof ( CLIENT ));
|
|
|
|
|
2001-12-14 09:13:43 +01:00
|
|
|
c->type = CLIENT_UNKNOWN;
|
|
|
|
c->conn_id = NONE;
|
2005-03-19 19:43:48 +01:00
|
|
|
c->oper_by_me = false;
|
2002-01-04 02:21:22 +01:00
|
|
|
c->hops = -1;
|
|
|
|
c->token = -1;
|
2002-01-08 00:42:12 +01:00
|
|
|
c->mytoken = -1;
|
2001-12-23 23:04:37 +01:00
|
|
|
|
2001-12-14 09:13:43 +01:00
|
|
|
return c;
|
|
|
|
} /* New_Client */
|
|
|
|
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2002-05-27 15:09:26 +02:00
|
|
|
Generate_MyToken( CLIENT *Client )
|
2002-01-08 00:42:12 +01:00
|
|
|
{
|
|
|
|
CLIENT *c;
|
2005-03-19 19:43:48 +01:00
|
|
|
int token;
|
2002-01-08 00:42:12 +01:00
|
|
|
|
|
|
|
c = My_Clients;
|
|
|
|
token = 2;
|
|
|
|
while( c )
|
|
|
|
{
|
|
|
|
if( c->mytoken == token )
|
|
|
|
{
|
|
|
|
/* Das Token wurde bereits vergeben */
|
|
|
|
token++;
|
|
|
|
c = My_Clients;
|
|
|
|
continue;
|
|
|
|
}
|
2002-03-25 20:11:01 +01:00
|
|
|
else c = (CLIENT *)c->next;
|
2002-01-08 00:42:12 +01:00
|
|
|
}
|
|
|
|
Client->mytoken = token;
|
2009-01-10 00:44:34 +01:00
|
|
|
LogDebug("Assigned token %d to server \"%s\".", token, Client->id);
|
2002-01-08 00:42:12 +01:00
|
|
|
} /* Generate_MyToken */
|
|
|
|
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2002-12-23 00:29:09 +01:00
|
|
|
Adjust_Counters( CLIENT *Client )
|
|
|
|
{
|
2005-03-19 19:43:48 +01:00
|
|
|
long count;
|
2002-12-23 00:29:09 +01:00
|
|
|
|
|
|
|
assert( Client != NULL );
|
|
|
|
|
|
|
|
if( Client->type != CLIENT_USER ) return;
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2002-12-23 00:29:09 +01:00
|
|
|
if( Client->conn_id != NONE )
|
|
|
|
{
|
|
|
|
/* Local connection */
|
|
|
|
count = Client_MyUserCount( );
|
|
|
|
if( count > My_Max_Users ) My_Max_Users = count;
|
|
|
|
}
|
|
|
|
count = Client_UserCount( );
|
|
|
|
if( count > Max_Users ) Max_Users = count;
|
|
|
|
} /* Adjust_Counters */
|
|
|
|
|
|
|
|
|
2005-05-16 14:23:48 +02:00
|
|
|
/**
|
|
|
|
* Register client in My_Whowas structure for further recall by WHOWAS.
|
2005-06-12 18:39:42 +02:00
|
|
|
* Note: Only clients that have been connected at least 30 seconds will be
|
|
|
|
* registered to prevent automated IRC bots to "destroy" a nice server
|
|
|
|
* history database.
|
2005-05-16 14:23:48 +02:00
|
|
|
*/
|
2005-05-18 01:18:54 +02:00
|
|
|
GLOBAL void
|
|
|
|
Client_RegisterWhowas( CLIENT *Client )
|
2005-05-16 14:23:48 +02:00
|
|
|
{
|
|
|
|
int slot;
|
2006-03-11 11:33:30 +01:00
|
|
|
time_t now;
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2005-05-16 14:23:48 +02:00
|
|
|
assert( Client != NULL );
|
|
|
|
|
2011-07-10 14:45:33 +02:00
|
|
|
/* Don't register WHOWAS information when "MorePrivacy" is enabled. */
|
|
|
|
if (Conf_MorePrivacy)
|
|
|
|
return;
|
|
|
|
|
2006-03-11 11:33:30 +01:00
|
|
|
now = time(NULL);
|
2005-06-12 18:39:42 +02:00
|
|
|
/* Don't register clients that were connected less than 30 seconds. */
|
2006-03-11 11:33:30 +01:00
|
|
|
if( now - Client->starttime < 30 )
|
2005-06-12 18:39:42 +02:00
|
|
|
return;
|
|
|
|
|
2005-05-16 14:23:48 +02:00
|
|
|
slot = Last_Whowas + 1;
|
|
|
|
if( slot >= MAX_WHOWAS || slot < 0 ) slot = 0;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
Log( LOG_DEBUG, "Saving WHOWAS information to slot %d ...", slot );
|
|
|
|
#endif
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2006-03-11 11:33:30 +01:00
|
|
|
My_Whowas[slot].time = now;
|
2005-05-16 14:23:48 +02:00
|
|
|
strlcpy( My_Whowas[slot].id, Client_ID( Client ),
|
|
|
|
sizeof( My_Whowas[slot].id ));
|
|
|
|
strlcpy( My_Whowas[slot].user, Client_User( Client ),
|
|
|
|
sizeof( My_Whowas[slot].user ));
|
2010-08-17 21:02:39 +02:00
|
|
|
strlcpy( My_Whowas[slot].host, Client_HostnameCloaked( Client ),
|
2005-05-16 14:23:48 +02:00
|
|
|
sizeof( My_Whowas[slot].host ));
|
|
|
|
strlcpy( My_Whowas[slot].info, Client_Info( Client ),
|
|
|
|
sizeof( My_Whowas[slot].info ));
|
|
|
|
strlcpy( My_Whowas[slot].server, Client_ID( Client_Introducer( Client )),
|
|
|
|
sizeof( My_Whowas[slot].server ));
|
2006-10-07 12:40:52 +02:00
|
|
|
|
2005-05-16 14:23:48 +02:00
|
|
|
Last_Whowas = slot;
|
2005-05-18 01:18:54 +02:00
|
|
|
} /* Client_RegisterWhowas */
|
2005-05-16 14:23:48 +02:00
|
|
|
|
|
|
|
|
2010-06-26 00:31:08 +02:00
|
|
|
GLOBAL const char *
|
2008-08-16 17:19:27 +02:00
|
|
|
Client_TypeText(CLIENT *Client)
|
|
|
|
{
|
|
|
|
assert(Client != NULL);
|
|
|
|
switch (Client_Type(Client)) {
|
|
|
|
case CLIENT_USER:
|
|
|
|
return "User";
|
|
|
|
break;
|
|
|
|
case CLIENT_SERVICE:
|
|
|
|
return "Service";
|
|
|
|
break;
|
|
|
|
case CLIENT_SERVER:
|
|
|
|
return "Server";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return "Client";
|
|
|
|
}
|
|
|
|
} /* Client_TypeText */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destroy user or service client.
|
|
|
|
*/
|
|
|
|
static void
|
2009-04-12 01:09:42 +02:00
|
|
|
Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool SendQuit)
|
2008-08-16 17:19:27 +02:00
|
|
|
{
|
|
|
|
if(Client->conn_id != NONE) {
|
|
|
|
/* Local (directly connected) client */
|
|
|
|
Log(LOG_NOTICE,
|
|
|
|
"%s \"%s\" unregistered (connection %d): %s",
|
|
|
|
Client_TypeText(Client), Client_Mask(Client),
|
|
|
|
Client->conn_id, Txt);
|
2010-05-22 17:19:24 +02:00
|
|
|
Log_ServerNotice('c', "Client exiting: %s (%s@%s) [%s]",
|
|
|
|
Client_ID(Client), Client_User(Client),
|
|
|
|
Client_Hostname(Client), Txt);
|
2008-08-16 17:19:27 +02:00
|
|
|
|
|
|
|
if (SendQuit) {
|
|
|
|
/* Inforam all the other servers */
|
|
|
|
if (FwdMsg)
|
|
|
|
IRC_WriteStrServersPrefix(NULL,
|
|
|
|
Client, "QUIT :%s", FwdMsg );
|
|
|
|
else
|
|
|
|
IRC_WriteStrServersPrefix(NULL,
|
|
|
|
Client, "QUIT :");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Remote client */
|
|
|
|
LogDebug("%s \"%s\" unregistered: %s",
|
|
|
|
Client_TypeText(Client), Client_Mask(Client), Txt);
|
|
|
|
|
|
|
|
if(SendQuit) {
|
|
|
|
/* Inform all the other servers, but the ones in the
|
|
|
|
* direction we got the QUIT from */
|
|
|
|
if(FwdMsg)
|
|
|
|
IRC_WriteStrServersPrefix(Client_NextHop(Client),
|
|
|
|
Client, "QUIT :%s", FwdMsg );
|
|
|
|
else
|
|
|
|
IRC_WriteStrServersPrefix(Client_NextHop(Client),
|
|
|
|
Client, "QUIT :" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unregister client from channels */
|
|
|
|
Channel_Quit(Client, FwdMsg ? FwdMsg : Client->id);
|
|
|
|
|
|
|
|
/* Register client in My_Whowas structure */
|
|
|
|
Client_RegisterWhowas(Client);
|
|
|
|
} /* Destroy_UserOrService */
|
|
|
|
|
|
|
|
|
2008-04-09 19:03:24 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
GLOBAL void
|
|
|
|
Client_DebugDump(void)
|
|
|
|
{
|
|
|
|
CLIENT *c;
|
|
|
|
|
|
|
|
Log(LOG_DEBUG, "Client status:");
|
|
|
|
c = My_Clients;
|
|
|
|
while (c) {
|
|
|
|
Log(LOG_DEBUG,
|
2010-09-10 21:10:17 +02:00
|
|
|
" - %s: type=%d, host=%s, user=%s, conn=%d, start=%ld, flags=%s",
|
2008-04-09 19:03:24 +02:00
|
|
|
Client_ID(c), Client_Type(c), Client_Hostname(c),
|
|
|
|
Client_User(c), Client_Conn(c), Client_StartTime(c),
|
|
|
|
Client_Flags(c));
|
|
|
|
c = (CLIENT *)c->next;
|
|
|
|
}
|
|
|
|
} /* Client_DumpClients */
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2001-12-14 09:13:43 +01:00
|
|
|
/* -eof- */
|