+ /* 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.
+ *
+ * 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)
+{
+ char Cloak_Buffer[CLIENT_HOST_LEN];
+
+ assert(Client != NULL);
+ if (!Origin)
+ Origin = Client_ThisServer();
+
+ if (!Client->cloaked) {
+ Client->cloaked = malloc(CLIENT_HOST_LEN);
+ if (!Client->cloaked)
+ return;
+ }
+
+ if (!Hostname) {
+ /* Generate new cloaked hostname */
+ if (*Conf_CloakHostModeX) {
+ strlcpy(Cloak_Buffer, Client->host,
+ sizeof(Cloak_Buffer));
+ strlcat(Cloak_Buffer, Conf_CloakHostSalt,
+ sizeof(Cloak_Buffer));
+ snprintf(Client->cloaked, CLIENT_HOST_LEN,
+ Conf_CloakHostModeX, Hash(Cloak_Buffer));
+ } else
+ strlcpy(Client->cloaked, Client_ID(Client->introducer),
+ CLIENT_HOST_LEN);
+ } else
+ strlcpy(Client->cloaked, Hostname, CLIENT_HOST_LEN);
+ 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);
+}