1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD 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, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
8 /**
9  * @file tcp_admin.cpp Basic functions to receive and send TCP packets to and from the admin network.
10  */
11 
12 #include "../../stdafx.h"
13 
14 #include "../network_internal.h"
15 #include "tcp_admin.h"
16 #include "../../debug.h"
17 
18 #include "../../safeguards.h"
19 
20 /* Make sure that these enums match. */
21 static_assert((int)CRR_MANUAL    == (int)ADMIN_CRR_MANUAL);
22 static_assert((int)CRR_AUTOCLEAN == (int)ADMIN_CRR_AUTOCLEAN);
23 static_assert((int)CRR_BANKRUPT  == (int)ADMIN_CRR_BANKRUPT);
24 static_assert((int)CRR_END       == (int)ADMIN_CRR_END);
25 
26 /**
27  * Create the admin handler for the given socket.
28  * @param s The socket to communicate over.
29  */
NetworkAdminSocketHandler(SOCKET s)30 NetworkAdminSocketHandler::NetworkAdminSocketHandler(SOCKET s) : status(ADMIN_STATUS_INACTIVE)
31 {
32 	this->sock = s;
33 }
34 
CloseConnection(bool error)35 NetworkRecvStatus NetworkAdminSocketHandler::CloseConnection(bool error)
36 {
37 	delete this;
38 	return NETWORK_RECV_STATUS_CLIENT_QUIT;
39 }
40 
41 /**
42  * Handle the given packet, i.e. pass it to the right parser receive command.
43  * @param p the packet to handle.
44  * @return #NetworkRecvStatus of handling.
45  */
HandlePacket(Packet * p)46 NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p)
47 {
48 	PacketAdminType type = (PacketAdminType)p->Recv_uint8();
49 
50 	switch (this->HasClientQuit() ? INVALID_ADMIN_PACKET : type) {
51 		case ADMIN_PACKET_ADMIN_JOIN:             return this->Receive_ADMIN_JOIN(p);
52 		case ADMIN_PACKET_ADMIN_QUIT:             return this->Receive_ADMIN_QUIT(p);
53 		case ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY: return this->Receive_ADMIN_UPDATE_FREQUENCY(p);
54 		case ADMIN_PACKET_ADMIN_POLL:             return this->Receive_ADMIN_POLL(p);
55 		case ADMIN_PACKET_ADMIN_CHAT:             return this->Receive_ADMIN_CHAT(p);
56 		case ADMIN_PACKET_ADMIN_EXTERNAL_CHAT:    return this->Receive_ADMIN_EXTERNAL_CHAT(p);
57 		case ADMIN_PACKET_ADMIN_RCON:             return this->Receive_ADMIN_RCON(p);
58 		case ADMIN_PACKET_ADMIN_GAMESCRIPT:       return this->Receive_ADMIN_GAMESCRIPT(p);
59 		case ADMIN_PACKET_ADMIN_PING:             return this->Receive_ADMIN_PING(p);
60 
61 		case ADMIN_PACKET_SERVER_FULL:            return this->Receive_SERVER_FULL(p);
62 		case ADMIN_PACKET_SERVER_BANNED:          return this->Receive_SERVER_BANNED(p);
63 		case ADMIN_PACKET_SERVER_ERROR:           return this->Receive_SERVER_ERROR(p);
64 		case ADMIN_PACKET_SERVER_PROTOCOL:        return this->Receive_SERVER_PROTOCOL(p);
65 		case ADMIN_PACKET_SERVER_WELCOME:         return this->Receive_SERVER_WELCOME(p);
66 		case ADMIN_PACKET_SERVER_NEWGAME:         return this->Receive_SERVER_NEWGAME(p);
67 		case ADMIN_PACKET_SERVER_SHUTDOWN:        return this->Receive_SERVER_SHUTDOWN(p);
68 
69 		case ADMIN_PACKET_SERVER_DATE:            return this->Receive_SERVER_DATE(p);
70 		case ADMIN_PACKET_SERVER_CLIENT_JOIN:     return this->Receive_SERVER_CLIENT_JOIN(p);
71 		case ADMIN_PACKET_SERVER_CLIENT_INFO:     return this->Receive_SERVER_CLIENT_INFO(p);
72 		case ADMIN_PACKET_SERVER_CLIENT_UPDATE:   return this->Receive_SERVER_CLIENT_UPDATE(p);
73 		case ADMIN_PACKET_SERVER_CLIENT_QUIT:     return this->Receive_SERVER_CLIENT_QUIT(p);
74 		case ADMIN_PACKET_SERVER_CLIENT_ERROR:    return this->Receive_SERVER_CLIENT_ERROR(p);
75 		case ADMIN_PACKET_SERVER_COMPANY_NEW:     return this->Receive_SERVER_COMPANY_NEW(p);
76 		case ADMIN_PACKET_SERVER_COMPANY_INFO:    return this->Receive_SERVER_COMPANY_INFO(p);
77 		case ADMIN_PACKET_SERVER_COMPANY_UPDATE:  return this->Receive_SERVER_COMPANY_UPDATE(p);
78 		case ADMIN_PACKET_SERVER_COMPANY_REMOVE:  return this->Receive_SERVER_COMPANY_REMOVE(p);
79 		case ADMIN_PACKET_SERVER_COMPANY_ECONOMY: return this->Receive_SERVER_COMPANY_ECONOMY(p);
80 		case ADMIN_PACKET_SERVER_COMPANY_STATS:   return this->Receive_SERVER_COMPANY_STATS(p);
81 		case ADMIN_PACKET_SERVER_CHAT:            return this->Receive_SERVER_CHAT(p);
82 		case ADMIN_PACKET_SERVER_RCON:            return this->Receive_SERVER_RCON(p);
83 		case ADMIN_PACKET_SERVER_CONSOLE:         return this->Receive_SERVER_CONSOLE(p);
84 		case ADMIN_PACKET_SERVER_CMD_NAMES:       return this->Receive_SERVER_CMD_NAMES(p);
85 		case ADMIN_PACKET_SERVER_CMD_LOGGING:     return this->Receive_SERVER_CMD_LOGGING(p);
86 		case ADMIN_PACKET_SERVER_RCON_END:        return this->Receive_SERVER_RCON_END(p);
87 		case ADMIN_PACKET_SERVER_PONG:            return this->Receive_SERVER_PONG(p);
88 
89 		default:
90 			if (this->HasClientQuit()) {
91 				Debug(net, 0, "[tcp/admin] Received invalid packet type {} from '{}' ({})", type, this->admin_name, this->admin_version);
92 			} else {
93 				Debug(net, 0, "[tcp/admin] Received illegal packet from '{}' ({})", this->admin_name, this->admin_version);
94 			}
95 
96 			this->CloseConnection();
97 			return NETWORK_RECV_STATUS_MALFORMED_PACKET;
98 	}
99 }
100 
101 /**
102  * Do the actual receiving of packets.
103  * As long as HandlePacket returns OKAY packets are handled. Upon
104  * failure, or no more packets to process the last result of
105  * HandlePacket is returned.
106  * @return #NetworkRecvStatus of the last handled packet.
107  */
ReceivePackets()108 NetworkRecvStatus NetworkAdminSocketHandler::ReceivePackets()
109 {
110 	Packet *p;
111 	while ((p = this->ReceivePacket()) != nullptr) {
112 		NetworkRecvStatus res = this->HandlePacket(p);
113 		delete p;
114 		if (res != NETWORK_RECV_STATUS_OKAY) return res;
115 	}
116 
117 	return NETWORK_RECV_STATUS_OKAY;
118 }
119 
120 /**
121  * Helper for logging receiving invalid packets.
122  * @param type The received packet type.
123  * @return The status the network should have, in this case: "malformed packet error".
124  */
ReceiveInvalidPacket(PacketAdminType type)125 NetworkRecvStatus NetworkAdminSocketHandler::ReceiveInvalidPacket(PacketAdminType type)
126 {
127 	Debug(net, 0, "[tcp/admin] Received illegal packet type {} from admin {} ({})", type, this->admin_name, this->admin_version);
128 	return NETWORK_RECV_STATUS_MALFORMED_PACKET;
129 }
130 
Receive_ADMIN_JOIN(Packet * p)131 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_JOIN); }
Receive_ADMIN_QUIT(Packet * p)132 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_QUIT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_QUIT); }
Receive_ADMIN_UPDATE_FREQUENCY(Packet * p)133 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_UPDATE_FREQUENCY(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY); }
Receive_ADMIN_POLL(Packet * p)134 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_POLL(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_POLL); }
Receive_ADMIN_CHAT(Packet * p)135 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_CHAT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_CHAT); }
Receive_ADMIN_EXTERNAL_CHAT(Packet * p)136 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_EXTERNAL_CHAT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_EXTERNAL_CHAT); }
Receive_ADMIN_RCON(Packet * p)137 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_RCON); }
Receive_ADMIN_GAMESCRIPT(Packet * p)138 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_GAMESCRIPT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_GAMESCRIPT); }
Receive_ADMIN_PING(Packet * p)139 NetworkRecvStatus NetworkAdminSocketHandler::Receive_ADMIN_PING(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_ADMIN_PING); }
140 
Receive_SERVER_FULL(Packet * p)141 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_FULL(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_FULL); }
Receive_SERVER_BANNED(Packet * p)142 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_BANNED(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_BANNED); }
Receive_SERVER_ERROR(Packet * p)143 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_ERROR(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_ERROR); }
Receive_SERVER_PROTOCOL(Packet * p)144 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_PROTOCOL(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_PROTOCOL); }
Receive_SERVER_WELCOME(Packet * p)145 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_WELCOME(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_WELCOME); }
Receive_SERVER_NEWGAME(Packet * p)146 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_NEWGAME(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_NEWGAME); }
Receive_SERVER_SHUTDOWN(Packet * p)147 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_SHUTDOWN(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_SHUTDOWN); }
148 
Receive_SERVER_DATE(Packet * p)149 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_DATE(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_DATE); }
Receive_SERVER_CLIENT_JOIN(Packet * p)150 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CLIENT_JOIN(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CLIENT_JOIN); }
Receive_SERVER_CLIENT_INFO(Packet * p)151 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CLIENT_INFO(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CLIENT_INFO); }
Receive_SERVER_CLIENT_UPDATE(Packet * p)152 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CLIENT_UPDATE(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CLIENT_UPDATE); }
Receive_SERVER_CLIENT_QUIT(Packet * p)153 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CLIENT_QUIT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CLIENT_QUIT); }
Receive_SERVER_CLIENT_ERROR(Packet * p)154 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CLIENT_ERROR(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CLIENT_ERROR); }
Receive_SERVER_COMPANY_NEW(Packet * p)155 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_COMPANY_NEW(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_COMPANY_NEW); }
Receive_SERVER_COMPANY_INFO(Packet * p)156 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_COMPANY_INFO); }
Receive_SERVER_COMPANY_UPDATE(Packet * p)157 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_COMPANY_UPDATE(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_COMPANY_UPDATE); }
Receive_SERVER_COMPANY_REMOVE(Packet * p)158 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_COMPANY_REMOVE(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_COMPANY_REMOVE); }
Receive_SERVER_COMPANY_ECONOMY(Packet * p)159 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_COMPANY_ECONOMY(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_COMPANY_ECONOMY); }
Receive_SERVER_COMPANY_STATS(Packet * p)160 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_COMPANY_STATS(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_COMPANY_STATS); }
Receive_SERVER_CHAT(Packet * p)161 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CHAT(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CHAT); }
Receive_SERVER_RCON(Packet * p)162 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_RCON(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_RCON); }
Receive_SERVER_CONSOLE(Packet * p)163 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CONSOLE(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CONSOLE); }
Receive_SERVER_CMD_NAMES(Packet * p)164 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CMD_NAMES(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CMD_NAMES); }
Receive_SERVER_CMD_LOGGING(Packet * p)165 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_CMD_LOGGING(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_CMD_LOGGING); }
Receive_SERVER_RCON_END(Packet * p)166 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_RCON_END(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_RCON_END); }
Receive_SERVER_PONG(Packet * p)167 NetworkRecvStatus NetworkAdminSocketHandler::Receive_SERVER_PONG(Packet *p) { return this->ReceiveInvalidPacket(ADMIN_PACKET_SERVER_PONG); }
168