/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
*
* 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
* Client management.
*/
-#include "imp.h"
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
+#include <time.h>
#include <netdb.h>
-#include "defines.h"
#include "conn.h"
-
-#include "exp.h"
-#include "client.h"
-
-#include <imp.h>
#include "ngircd.h"
#include "channel.h"
#include "conf.h"
#include "match.h"
#include "messages.h"
-#include <exp.h>
-
#define GETID_LEN (CLIENT_NICK_LEN-1) + 1 + (CLIENT_USER_LEN-1) + 1 + (CLIENT_HOST_LEN-1) + 1
static CLIENT *This_Server, *My_Clients;
static void Generate_MyToken PARAMS(( CLIENT *Client ));
static void Adjust_Counters PARAMS(( CLIENT *Client ));
+static void Free_Client PARAMS(( CLIENT **Client ));
+
static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer,
CLIENT *TopServer, int Type, const char *ID,
const char *User, const char *Hostname, const char *Info,
Client_Init( void )
{
struct hostent *h;
-
+
This_Server = New_Client_Struct( );
if( ! This_Server )
{
Client_SetInfo( This_Server, Conf_ServerInfo );
My_Clients = This_Server;
-
+
memset( &My_Whowas, 0, sizeof( My_Whowas ));
} /* Client_Init */
if( NGIRCd_SignalRestart ) Client_Destroy( This_Server, "Server going down (restarting).", NULL, false );
else Client_Destroy( This_Server, "Server going down.", NULL, false );
-
+
cnt = 0;
c = My_Clients;
- while( c )
- {
+ while(c) {
cnt++;
next = (CLIENT *)c->next;
- if (c->account_name)
- free(c->account_name);
- if (c->cloaked)
- free(c->cloaked);
- free( c );
+ Free_Client(&c);
c = next;
}
- if( cnt ) Log( LOG_INFO, "Freed %d client structure%s.", cnt, cnt == 1 ? "" : "s" );
+ if (cnt)
+ Log(LOG_INFO, "Freed %d client structure%s.",
+ cnt, cnt == 1 ? "" : "s");
} /* Client_Exit */
Generate_MyToken(client);
if (Client_HasMode(client, 'a'))
- strlcpy(client->away, DEFAULT_AWAY_MSG, sizeof(client->away));
+ client->away = strdup(DEFAULT_AWAY_MSG);
client->next = (POINTER *)My_Clients;
My_Clients = client;
Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool SendQuit )
{
/* remove a client */
-
+
CLIENT *last, *c;
- char msg[LINE_LEN];
+ char msg[COMMAND_LEN];
const char *txt;
assert( Client != NULL );
}
}
- if (c->account_name)
- free(c->account_name);
- if (c->cloaked)
- free(c->cloaked);
- free( c );
+ Free_Client(&c);
break;
}
last = c;
assert(Client != NULL);
assert(Hostname != NULL);
- if (strlen(Conf_CloakHost)) {
+ /* Only cloak the hostmask if it has not yet been cloaked.
+ * The period or colon indicates it's still an IP address.
+ * An empty string means a rDNS lookup did not happen (yet). */
+ if (Conf_CloakHost[0] && (!Client->host[0] || strchr(Client->host, '.')
+ || strchr(Client->host, ':'))) {
char cloak[GETID_LEN];
strlcpy(cloak, Hostname, GETID_LEN);
} /* Client_SetHostname */
+/**
+ * Set IP address to display for a client.
+ *
+ * @param Client The client.
+ * @param IPAText Textual representation of the IP address or NULL to unset.
+ */
+GLOBAL void
+Client_SetIPAText(CLIENT *Client, const char *IPAText)
+{
+ assert(Client != NULL);
+
+ if (Client->ipa_text)
+ free(Client->ipa_text);
+
+ if (*IPAText)
+ Client->ipa_text = strndup(IPAText, CLIENT_HOST_LEN - 1);
+ else
+ Client->ipa_text = NULL;
+}
+
+
GLOBAL void
Client_SetID( CLIENT *Client, const char *ID )
{
assert( Client != NULL );
assert( ID != NULL );
-
+
strlcpy( Client->id, ID, sizeof( Client->id ));
if (Conf_CloakUserToNick) {
assert(Client != NULL);
assert(User != NULL);
-#if defined(PAM) && defined(IDENTAUTH)
+#if defined(PAM)
strlcpy(Client->orig_user, User, sizeof(Client->orig_user));
#endif
} /* Client_SetOrigUser */
assert( Client != NULL );
assert( Txt != NULL );
- strlcpy( Client->away, Txt, sizeof( Client->away ));
+ if (Client->away)
+ free(Client->away);
+
+ Client->away = strndup(Txt, CLIENT_AWAY_LEN - 1);
+
LogDebug("%s \"%s\" is away: %s", Client_TypeText(Client),
Client_Mask(Client), Txt);
} /* Client_SetAway */
} /* Client_SetIntroducer */
-GLOBAL void
-Client_SetOperByMe( CLIENT *Client, bool OperByMe )
-{
- assert( Client != NULL );
- Client->oper_by_me = OperByMe;
-} /* Client_SetOperByMe */
-
-
GLOBAL bool
Client_ModeAdd( CLIENT *Client, char Mode )
{
/**
- * Get client structure ("introducer") identfied by a server token.
+ * Get client structure ("introducer") identified by a server token.
* @return CLIENT structure or NULL if none could be found.
*/
GLOBAL CLIENT *
{
assert( Client != NULL );
-#ifdef DEBUG
if(Client->type == CLIENT_USER)
assert(strlen(Client->id) < Conf_MaxNickLength);
-#endif
-
+
if( Client->id[0] ) return Client->id;
else return "*";
} /* Client_ID */
*/
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
return Client->cloaked;
}
+GLOBAL const char *
+Client_IPAText(CLIENT *Client)
+{
+ assert(Client != NULL);
+
+ /* Not a local client? */
+ if (Client_Conn(Client) <= NONE)
+ return "0.0.0.0";
+
+ if (!Client->ipa_text)
+ return Conn_GetIPAInfo(Client_Conn(Client));
+ else
+ return Client->ipa_text;
+}
+
/**
* Update (and generate, if necessary) the cloaked hostname of a client.
*
} /* Client_Flags */
-GLOBAL bool
-Client_OperByMe( CLIENT *Client )
-{
- assert( Client != NULL );
- return Client->oper_by_me;
-} /* Client_OperByMe */
-
-
GLOBAL int
Client_Hops( CLIENT *Client )
{
GLOBAL void
Client_Introduce(CLIENT *From, CLIENT *Client, int Type)
{
+ int server;
+
/* Set client type (user or service) */
Client_SetType(Client, Type);
if (From) {
- if (Conf_NickIsService(Conf_GetServer(Client_Conn(From)),
- Client_ID(Client)))
+ server = Conf_GetServer(Client_Conn(From));
+ if (server > NONE && Conf_NickIsService(server, Client_ID(Client)))
Client_SetType(Client, CLIENT_SERVICE);
LogDebug("%s \"%s\" (+%s) registered (via %s, on %s, %d hop%s).",
Client_TypeText(Client), Client_Mask(Client),
} /* MyCount */
+/**
+ * Allocate and initialize new CLIENT structure.
+ *
+ * @return Pointer to CLIENT structure or NULL on error.
+ */
static CLIENT *
New_Client_Struct( void )
{
c->type = CLIENT_UNKNOWN;
c->conn_id = NONE;
- c->oper_by_me = false;
c->hops = -1;
c->token = -1;
c->mytoken = -1;
return c;
-} /* New_Client */
+}
+/**
+ * Free a CLIENT structure and its member variables.
+ */
+static void
+Free_Client(CLIENT **Client)
+{
+ assert(Client != NULL);
+ assert(*Client != NULL);
+
+ if ((*Client)->account_name)
+ free((*Client)->account_name);
+ if ((*Client)->away)
+ free((*Client)->away);
+ if ((*Client)->cloaked)
+ free((*Client)->cloaked);
+ if ((*Client)->ipa_text)
+ free((*Client)->ipa_text);
+
+ free(*Client);
+ *Client = NULL;
+}
static void
Generate_MyToken( CLIENT *Client )
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
+ LogDebug( "Saving WHOWAS information to slot %d ...", slot );
My_Whowas[slot].time = now;
strlcpy( My_Whowas[slot].id, Client_ID( Client ),
} /* Client_Announce */
-#ifdef DEBUG
GLOBAL void
Client_DebugDump(void)
{
CLIENT *c;
- Log(LOG_DEBUG, "Client status:");
+ LogDebug("Client status:");
c = My_Clients;
while (c) {
- Log(LOG_DEBUG,
+ LogDebug(
" - %s: type=%d, host=%s, user=%s, conn=%d, start=%ld, flags=%s",
Client_ID(c), Client_Type(c), Client_Hostname(c),
Client_User(c), Client_Conn(c), Client_StartTime(c),
}
} /* Client_DumpClients */
-#endif
/* -eof- */