#endif
-
/**
* Return the hostname of a client.
* @param Client Pointer to client structure
{
assert (Client != NULL);
return Client->host;
-} /* Client_Hostname */
+}
+/**
+ * Return the cloaked hostname of a client, if set.
+ * @param Client Pointer to the client structure.
+ * @return Pointer to the cloaked hostname or NULL if not set.
+ */
+GLOBAL char *
+Client_HostnameCloaked(CLIENT *Client)
+{
+ assert(Client != NULL);
+ return Client->cloaked;
+}
/**
- * Get potentially cloaked hostname of a client.
+ * Get (potentially cloaked) hostname of a client to display it to other users.
*
* If the client has not enabled cloaking, the real hostname is used.
* Please note that this function uses a global static buffer, so you can't
* @return Pointer to client hostname
*/
GLOBAL char *
-Client_HostnameCloaked(CLIENT *Client)
+Client_HostnameDisplayed(CLIENT *Client)
{
- static char Cloak_Buffer[CLIENT_HOST_LEN];
-
assert(Client != NULL);
+ /* Client isn't cloaked at all, return real hostname: */
if (!Client_HasMode(Client, 'x'))
return Client_Hostname(Client);
- /* Do simple mapping to the server ID? */
- if (!*Conf_CloakHostModeX)
- return Client_ID(Client->introducer);
+ /* Use an already saved cloaked hostname, if there is one */
+ if (Client->cloaked[0])
+ return Client->cloaked;
- strlcpy(Cloak_Buffer, Client->host, CLIENT_HOST_LEN);
- strlcat(Cloak_Buffer, Conf_CloakHostSalt, CLIENT_HOST_LEN);
-
- snprintf(Cloak_Buffer, CLIENT_HOST_LEN, Conf_CloakHostModeX,
- Hash(Cloak_Buffer));
+ Client_UpdateCloakedHostname(Client, NULL, NULL);
+ return Client->cloaked;
+}
- return Cloak_Buffer;
-} /* Client_HostnameCloaked */
+/**
+ * Update (and generate, if necessary) the cloaked hostname of a client.
+ *
+ * The newly set cloaked hostname is announced in the network using METADATA
+ * commands to peers that support this feature.
+ *
+ * @param Client The client of which the cloaked hostname should be updated.
+ * @param Origin The originator of the hostname change, or NULL if this server.
+ * @param Hostname The new cloaked hostname, or NULL if it should be generated.
+ */
+GLOBAL void
+Client_UpdateCloakedHostname(CLIENT *Client, CLIENT *Origin,
+ const char *Hostname)
+{
+ static char Cloak_Buffer[CLIENT_HOST_LEN];
+ assert(Client != NULL);
+ if (!Origin)
+ Origin = Client_ThisServer();
+
+ if (!Hostname) {
+ /* Generate new cloaked hostname */
+ if (*Conf_CloakHostModeX) {
+ strlcpy(Cloak_Buffer, Client->host, CLIENT_HOST_LEN);
+ strlcat(Cloak_Buffer, Conf_CloakHostSalt,
+ CLIENT_HOST_LEN);
+ snprintf(Client->cloaked, sizeof(Client->cloaked),
+ Conf_CloakHostModeX, Hash(Cloak_Buffer));
+ } else
+ strlcpy(Client->cloaked, Client_ID(Client->introducer),
+ sizeof(Client->cloaked));
+ } else
+ strlcpy(Client->cloaked, Hostname, sizeof(Client->cloaked));
+ LogDebug("Cloaked hostname of \"%s\" updated to \"%s\"",
+ Client_ID(Client), Client->cloaked);
+
+ /* Inform other servers in the network */
+ IRC_WriteStrServersPrefixFlag(Client_NextHop(Origin), Origin, 'M',
+ "METADATA %s cloakhost :%s",
+ Client_ID(Client), Client->cloaked);
+}
GLOBAL char *
Client_Modes( CLIENT *Client )
return Client_Mask(Client);
snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user,
- Client_HostnameCloaked(Client));
+ Client_HostnameDisplayed(Client));
return Mask_Buffer;
} /* Client_MaskCloaked */
sizeof( My_Whowas[slot].id ));
strlcpy( My_Whowas[slot].user, Client_User( Client ),
sizeof( My_Whowas[slot].user ));
- strlcpy( My_Whowas[slot].host, Client_HostnameCloaked( Client ),
+ strlcpy( My_Whowas[slot].host, Client_HostnameDisplayed( Client ),
sizeof( My_Whowas[slot].host ));
strlcpy( My_Whowas[slot].info, Client_Info( Client ),
sizeof( My_Whowas[slot].info ));