unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

sinfo.c (4923B)

      1 /*
      2  * cmd_sinfo - Server information
      3  * (C) Copyright 2019 Bram Matthys (Syzop) and the UnrealIRCd team.
      4  * License: GPLv2 or later
      5  */
      6 
      7 #include "unrealircd.h"
      8 
      9 ModuleHeader MOD_HEADER
     10   = {
     11 	"sinfo",
     12 	"5.0",
     13 	"Server information",
     14 	"UnrealIRCd Team",
     15 	"unrealircd-6",
     16     };
     17 
     18 /* Forward declarations */
     19 CMD_FUNC(cmd_sinfo);
     20 
     21 MOD_INIT()
     22 {
     23 	MARK_AS_OFFICIAL_MODULE(modinfo);
     24 	CommandAdd(modinfo->handle, "SINFO", cmd_sinfo, MAXPARA, CMD_USER|CMD_SERVER);
     25 
     26 	return MOD_SUCCESS;
     27 }
     28 
     29 MOD_LOAD()
     30 {
     31 	return MOD_SUCCESS;
     32 }
     33 
     34 MOD_UNLOAD()
     35 {
     36 	return MOD_SUCCESS;
     37 }
     38 
     39 /** SINFO server-to-server command.
     40  * Technical documentation is available at:
     41  * https://www.unrealircd.org/docs/Server_protocol:SINFO_command
     42  * ^ contains important remarks regarding when to send it and when not.
     43  */
     44 CMD_FUNC(sinfo_server)
     45 {
     46 	char buf[512];
     47 
     48 	if (MyConnect(client))
     49 	{
     50 		/* It is a protocol violation to send an SINFO for yourself,
     51 		 * eg if you are server 001, then you cannot send :001 SINFO ....
     52 		 * Exiting the client may seem harsh, but this way we force users
     53 		 * to use the correct protocol. If we would not do this then some
     54 		 * services coders may think they should use only SINFO while in
     55 		 * fact for directly connected servers they should use things like
     56 		 * PROTOCTL CHANMODES=... USERMODES=... NICKCHARS=.... etc, and
     57 		 * failure to do so will lead to potential desyncs or other major
     58 		 * issues.
     59 		 */
     60 		exit_client(client, NULL, "Protocol error: you cannot send SINFO about yourself");
     61 		return;
     62 	}
     63 
     64 	/* :SID SINFO up_since protocol umodes chanmodes nickchars :software name
     65 	 *               1        2        3      4        5        6 (last one)
     66 	 * If we extend it then 'software name' will still be the last one, so
     67 	 * it may become 7, 8 or 9. New elements are inserted right before it.
     68 	 */
     69 
     70 	if ((parc < 6) || BadPtr(parv[6]))
     71 	{
     72 		sendnumeric(client, ERR_NEEDMOREPARAMS, "SINFO");
     73 		return;
     74 	}
     75 
     76 	client->server->boottime = atol(parv[1]);
     77 	client->server->features.protocol = atoi(parv[2]);
     78 
     79 	if (!strcmp(parv[3], "*"))
     80 		safe_free(client->server->features.usermodes);
     81 	else
     82 		safe_strdup(client->server->features.usermodes, parv[3]);
     83 
     84 	if (!strcmp(parv[4], "*"))
     85 	{
     86 		safe_free(client->server->features.chanmodes[0]);
     87 		safe_free(client->server->features.chanmodes[1]);
     88 		safe_free(client->server->features.chanmodes[2]);
     89 		safe_free(client->server->features.chanmodes[3]);
     90 	} else {
     91 		parse_chanmodes_protoctl(client, parv[4]);
     92 	}
     93 
     94 	if (!strcmp(parv[5], "*"))
     95 		safe_free(client->server->features.nickchars);
     96 	else
     97 		safe_strdup(client->server->features.nickchars, parv[5]);
     98 
     99 	/* Software is always the last parameter. It is currently parv[6]
    100 	 * but may change later. So always use parv[parc-1].
    101 	 */
    102 	if (!strcmp(parv[parc-1], "*"))
    103 		safe_free(client->server->features.software);
    104 	else
    105 		safe_strdup(client->server->features.software, parv[parc-1]);
    106 
    107 	if (is_services_but_not_ulined(client))
    108 	{
    109 		char buf[512];
    110 		snprintf(buf, sizeof(buf), "Services detected but no ulines { } for server name %s", client->name);
    111 		exit_client_ex(client, &me, NULL, buf);
    112 		return;
    113 	}
    114 
    115 	/* Broadcast to 'the other side' of the net */
    116 	concat_params(buf, sizeof(buf), parc, parv);
    117 	sendto_server(client, 0, 0, NULL, ":%s SINFO %s", client->id, buf);
    118 }
    119 
    120 #define SafeDisplayStr(x)  ((x && *(x)) ? (x) : "-")
    121 CMD_FUNC(sinfo_user)
    122 {
    123 	Client *acptr;
    124 
    125 	if (!IsOper(client))
    126 	{
    127 		sendnumeric(client, ERR_NOPRIVILEGES);
    128 		return;
    129 	}
    130 
    131 	list_for_each_entry(acptr, &global_server_list, client_node)
    132 	{
    133 		sendtxtnumeric(client, "*** Server %s:", acptr->name);
    134 		sendtxtnumeric(client, "Protocol: %d",
    135 		               acptr->server->features.protocol);
    136 		sendtxtnumeric(client, "Software: %s",
    137 		               SafeDisplayStr(acptr->server->features.software));
    138 		if (!acptr->server->boottime)
    139 		{
    140 			sendtxtnumeric(client, "Up since: -");
    141 			sendtxtnumeric(client, "Uptime: -");
    142 		} else {
    143 			sendtxtnumeric(client, "Up since: %s",
    144 			               pretty_date(acptr->server->boottime));
    145 			sendtxtnumeric(client, "Uptime: %s",
    146 			               pretty_time_val(TStime() - acptr->server->boottime));
    147 		}
    148 		sendtxtnumeric(client, "User modes: %s",
    149 		               SafeDisplayStr(acptr->server->features.usermodes));
    150 		if (!acptr->server->features.chanmodes[0])
    151 		{
    152 			sendtxtnumeric(client, "Channel modes: -");
    153 		} else {
    154 			sendtxtnumeric(client, "Channel modes: %s,%s,%s,%s",
    155 			               SafeDisplayStr(acptr->server->features.chanmodes[0]),
    156 			               SafeDisplayStr(acptr->server->features.chanmodes[1]),
    157 			               SafeDisplayStr(acptr->server->features.chanmodes[2]),
    158 			               SafeDisplayStr(acptr->server->features.chanmodes[3]));
    159 		}
    160 		sendtxtnumeric(client, "Allowed nick characters: %s",
    161 		               SafeDisplayStr(acptr->server->features.nickchars));
    162 	}
    163 }
    164 
    165 CMD_FUNC(cmd_sinfo)
    166 {
    167 	if (IsServer(client))
    168 		CALL_CMD_FUNC(sinfo_server);
    169 	else if (MyUser(client))
    170 		CALL_CMD_FUNC(sinfo_user);
    171 }