2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
19 * Author : Maxim Mamontov <faust@stargazer.dp.ua>
24 #include "ur_functor.h"
26 #include "stg/common.h"
27 #include "stg/users.h"
28 #include "stg/user_property.h"
29 #include "stg/logger.h"
40 #include <netinet/ip.h>
43 #define MAX_SHORT_PCKT (3)
45 extern volatile time_t stgTime;
47 namespace RS = STG::RS;
48 using RS::REMOTE_SCRIPT;
50 extern "C" STG::Plugin* GetPlugin()
52 static REMOTE_SCRIPT plugin;
55 //-----------------------------------------------------------------------------
56 //-----------------------------------------------------------------------------
57 //-----------------------------------------------------------------------------
58 RS::SETTINGS::SETTINGS()
63 //-----------------------------------------------------------------------------
64 int RS::SETTINGS::ParseSettings(const ModuleSettings & s)
69 ///////////////////////////
71 auto pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
72 if (pvi == s.moduleParams.end() || pvi->value.empty())
74 errorStr = "Parameter \'Port\' not found.";
75 printfd(__FILE__, "Parameter 'Port' not found\n");
78 if (ParseIntInRange(pvi->value[0], 2, 65535, &p) != 0)
80 errorStr = "Cannot parse parameter \'Port\': " + errorStr;
81 printfd(__FILE__, "Cannot parse parameter 'Port'\n");
84 port = static_cast<uint16_t>(p);
85 ///////////////////////////
86 pv.param = "SendPeriod";
87 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
88 if (pvi == s.moduleParams.end() || pvi->value.empty())
90 errorStr = "Parameter \'SendPeriod\' not found.";
91 printfd(__FILE__, "Parameter 'SendPeriod' not found\n");
95 if (ParseIntInRange(pvi->value[0], 5, 600, &sendPeriod) != 0)
97 errorStr = "Cannot parse parameter \'SendPeriod\': " + errorStr;
98 printfd(__FILE__, "Cannot parse parameter 'SendPeriod'\n");
101 ///////////////////////////
102 pv.param = "UserParams";
103 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
104 if (pvi == s.moduleParams.end() || pvi->value.empty())
106 errorStr = "Parameter \'UserParams\' not found.";
107 printfd(__FILE__, "Parameter 'UserParams' not found\n");
110 userParams = pvi->value;
111 ///////////////////////////
112 pv.param = "Password";
113 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
114 if (pvi == s.moduleParams.end() || pvi->value.empty())
116 errorStr = "Parameter \'Password\' not found.";
117 printfd(__FILE__, "Parameter 'Password' not found\n");
120 password = pvi->value[0];
121 ///////////////////////////
122 pv.param = "SubnetFile";
123 pvi = find(s.moduleParams.begin(), s.moduleParams.end(), pv);
124 if (pvi == s.moduleParams.end() || pvi->value.empty())
126 errorStr = "Parameter \'SubnetFile\' not found.";
127 printfd(__FILE__, "Parameter 'SubnetFile' not found\n");
130 subnetFile = pvi->value[0];
132 NRMapParser nrMapParser;
134 if (!nrMapParser.ReadFile(subnetFile))
135 netRouters = nrMapParser.GetMap();
137 PluginLogger::get("rscript")("mod_rscript: error opening subnets file '%s'", subnetFile.c_str());
141 //-----------------------------------------------------------------------------
142 //-----------------------------------------------------------------------------
143 //-----------------------------------------------------------------------------
144 REMOTE_SCRIPT::REMOTE_SCRIPT()
150 logger(PluginLogger::get("rscript"))
153 //-----------------------------------------------------------------------------
154 void REMOTE_SCRIPT::Run(std::stop_token token)
157 sigfillset(&signalSet);
158 pthread_sigmask(SIG_BLOCK, &signalSet, nullptr);
162 while (!token.stop_requested())
170 //-----------------------------------------------------------------------------
171 int REMOTE_SCRIPT::ParseSettings()
173 auto ret = rsSettings.ParseSettings(settings);
175 errorStr = rsSettings.GetStrError();
177 sendPeriod = rsSettings.GetSendPeriod();
178 halfPeriod = sendPeriod / 2;
182 //-----------------------------------------------------------------------------
183 int REMOTE_SCRIPT::Start()
185 netRouters = rsSettings.GetSubnetsMap();
187 InitEncrypt(rsSettings.GetPassword());
189 m_onAddUserConn = users->onAdd([this](auto user){ AddUser(user); });
190 m_onDelUserConn = users->onDel([this](auto user){ DelUser(user); });
199 m_thread = std::jthread([this](auto token){ Run(std::move(token)); });
204 //-----------------------------------------------------------------------------
205 int REMOTE_SCRIPT::Stop()
210 m_thread.request_stop();
213 authorizedUsers.begin(),
214 authorizedUsers.end(),
215 [this](auto& kv){ Send(kv.second, true); }
222 //5 seconds to thread stops itself
223 for (int i = 0; i < 25 && isRunning; i++)
225 struct timespec ts = {0, 200000000};
226 nanosleep(&ts, nullptr);
232 logger("Cannot stop thread.");
240 //-----------------------------------------------------------------------------
241 int REMOTE_SCRIPT::Reload(const ModuleSettings & /*ms*/)
243 NRMapParser nrMapParser;
245 if (nrMapParser.ReadFile(rsSettings.GetMapFileName()))
247 errorStr = nrMapParser.GetErrorStr();
248 logger("Map file reading error: %s", errorStr.c_str());
253 std::lock_guard lock(m_mutex);
255 printfd(__FILE__, "REMOTE_SCRIPT::Reload()\n");
257 netRouters = nrMapParser.GetMap();
260 std::for_each(authorizedUsers.begin(),
261 authorizedUsers.end(),
262 UpdateRouter(*this));
264 logger("%s reloaded successfully.", rsSettings.GetMapFileName().c_str());
265 printfd(__FILE__, "REMOTE_SCRIPT::Reload() %s reloaded successfully.\n");
269 //-----------------------------------------------------------------------------
270 bool REMOTE_SCRIPT::PrepareNet()
272 sock = socket(AF_INET, SOCK_DGRAM, 0);
276 errorStr = "Cannot create socket.";
277 logger("Canot create a socket: %s", strerror(errno));
278 printfd(__FILE__, "Cannot create socket\n");
284 //-----------------------------------------------------------------------------
285 bool REMOTE_SCRIPT::FinalizeNet()
290 //-----------------------------------------------------------------------------
291 void REMOTE_SCRIPT::PeriodicSend()
293 std::lock_guard lock(m_mutex);
295 auto it = authorizedUsers.begin();
296 while (it != authorizedUsers.end())
298 if (difftime(stgTime, it->second.lastSentTime) - (rand() % halfPeriod) > sendPeriod)
305 //-----------------------------------------------------------------------------
307 bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t, RS::USER & rsu, bool forceDisconnect) const
309 bool REMOTE_SCRIPT::PreparePacket(char * buf, size_t bufSize, RS::USER & rsu, bool forceDisconnect) const
312 RS::PACKET_HEADER packetHead;
314 memset(packetHead.padding, 0, sizeof(packetHead.padding));
315 memcpy(packetHead.magic, RS_ID, sizeof(RS_ID));
316 packetHead.protoVer[0] = '0';
317 packetHead.protoVer[1] = '2';
320 packetHead.packetType = RS_DISCONNECT_PACKET;
321 printfd(__FILE__, "RSCRIPT: force disconnect for '%s'\n", rsu.user->GetLogin().c_str());
325 if (rsu.shortPacketsCount % MAX_SHORT_PCKT == 0)
328 packetHead.packetType = rsu.user->IsInetable() ? RS_CONNECT_PACKET : RS_DISCONNECT_PACKET;
329 if (rsu.user->IsInetable())
330 printfd(__FILE__, "RSCRIPT: connect for '%s'\n", rsu.user->GetLogin().c_str());
332 printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
337 packetHead.packetType = rsu.user->IsInetable() ? RS_ALIVE_PACKET : RS_DISCONNECT_PACKET;
338 if (rsu.user->IsInetable())
339 printfd(__FILE__, "RSCRIPT: alive for '%s'\n", rsu.user->GetLogin().c_str());
341 printfd(__FILE__, "RSCRIPT: disconnect for '%s'\n", rsu.user->GetLogin().c_str());
344 rsu.shortPacketsCount++;
345 rsu.lastSentTime = stgTime;
347 packetHead.ip = htonl(rsu.ip);
348 packetHead.id = htonl(rsu.user->GetID());
349 strncpy(reinterpret_cast<char*>(packetHead.login), rsu.user->GetLogin().c_str(), RS_LOGIN_LEN);
350 packetHead.login[RS_LOGIN_LEN - 1] = 0;
352 memcpy(buf, &packetHead, sizeof(packetHead));
354 if (packetHead.packetType == RS_ALIVE_PACKET)
359 RS::PACKET_TAIL packetTail;
361 memset(packetTail.padding, 0, sizeof(packetTail.padding));
362 memcpy(packetTail.magic, RS_ID, sizeof(RS_ID));
364 for (const auto& param : rsSettings.GetUserParams())
366 auto value = rsu.user->GetParamValue(param);
367 if (params.length() + value.length() > RS_PARAMS_LEN - 1)
369 logger("Script params string length %d exceeds the limit of %d symbols.", params.length() + value.length(), RS_PARAMS_LEN);
372 params += value + " ";
374 strncpy(reinterpret_cast<char*>(packetTail.params), params.c_str(), RS_PARAMS_LEN);
375 packetTail.params[RS_PARAMS_LEN - 1] = 0;
377 assert(sizeof(packetHead) + sizeof(packetTail) <= bufSize && "Insufficient buffer space");
379 Encrypt(buf + sizeof(packetHead), reinterpret_cast<char *>(&packetTail), sizeof(packetTail) / 8);
383 //-----------------------------------------------------------------------------
384 bool REMOTE_SCRIPT::Send(RS::USER & rsu, bool forceDisconnect) const
386 char buffer[RS_MAX_PACKET_LEN];
388 memset(buffer, 0, sizeof(buffer));
390 if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
392 printfd(__FILE__, "REMOTE_SCRIPT::Send() - Invalid packet length!\n");
396 for (const auto& ip : rsu.routers)
398 struct sockaddr_in sendAddr;
400 sendAddr.sin_family = AF_INET;
401 sendAddr.sin_port = htons(rsSettings.GetPort());
402 sendAddr.sin_addr.s_addr = ip;
404 return sendto(sock, buffer, sizeof(buffer), 0, reinterpret_cast<struct sockaddr*>(&sendAddr), sizeof(sendAddr)) > 0;
409 //-----------------------------------------------------------------------------
410 bool REMOTE_SCRIPT::SendDirect(RS::USER & rsu, uint32_t routerIP, bool forceDisconnect) const
412 char buffer[RS_MAX_PACKET_LEN];
414 if (PreparePacket(buffer, sizeof(buffer), rsu, forceDisconnect))
416 printfd(__FILE__, "REMOTE_SCRIPT::SendDirect() - Invalid packet length!\n");
420 struct sockaddr_in sendAddr;
422 sendAddr.sin_family = AF_INET;
423 sendAddr.sin_port = htons(rsSettings.GetPort());
424 sendAddr.sin_addr.s_addr = routerIP;
426 ssize_t res = sendto(sock, buffer, sizeof(buffer), 0, reinterpret_cast<struct sockaddr *>(&sendAddr), sizeof(sendAddr));
429 logger("sendto error: %s", strerror(errno));
431 return (res != sizeof(buffer));
433 //-----------------------------------------------------------------------------
434 bool REMOTE_SCRIPT::GetUsers()
438 int h = users->OpenSearch();
439 assert(h && "USERS::OpenSearch is always correct");
441 while (users->SearchNext(h, &u) != 0)
444 users->CloseSearch(h);
447 //-----------------------------------------------------------------------------
448 std::vector<uint32_t> REMOTE_SCRIPT::IP2Routers(uint32_t ip)
450 std::lock_guard lock(m_mutex);
451 for (auto& nr : netRouters)
452 if ((ip & nr.subnetMask) == (nr.subnetIP & nr.subnetMask))
456 //-----------------------------------------------------------------------------
457 void REMOTE_SCRIPT::SetUserNotifiers(UserPtr u)
459 m_conns.emplace_back(
461 u->afterCurrIPChange([this, u](auto, auto newVal){ addDelUser(u, newVal != 0); }),
462 u->afterConnectedChange([this, u](auto, auto newVal){ addDelUser(u, newVal); })
465 //-----------------------------------------------------------------------------
466 void REMOTE_SCRIPT::UnSetUserNotifiers(UserPtr u)
468 m_conns.erase(std::remove_if(m_conns.begin(), m_conns.end(),
469 [u](const auto& c){ return std::get<0>(c) == u->GetID(); }),
473 //-----------------------------------------------------------------------------
474 void REMOTE_SCRIPT::AddRSU(UserPtr user)
476 RS::USER rsu(IP2Routers(user->GetCurrIP()), user);
479 std::lock_guard lock(m_mutex);
480 authorizedUsers.insert(std::make_pair(user->GetCurrIP(), rsu));
482 //-----------------------------------------------------------------------------
483 void REMOTE_SCRIPT::DelRSU(UserPtr user)
485 std::lock_guard lock(m_mutex);
486 auto it = authorizedUsers.begin();
487 while (it != authorizedUsers.end())
489 if (it->second.user == user)
491 Send(it->second, true);
492 authorizedUsers.erase(it);
497 /*const auto it = authorizedUsers.find(user->GetCurrIP());
498 if (it != authorizedUsers.end())
500 Send(it->second, true);
501 authorizedUsers.erase(it);
504 //-----------------------------------------------------------------------------
505 void REMOTE_SCRIPT::addDelUser(UserPtr user, bool toAdd)
512 //-----------------------------------------------------------------------------
513 void REMOTE_SCRIPT::InitEncrypt(const std::string & password) const
515 unsigned char keyL[PASSWD_LEN]; // Пароль для шифровки
516 memset(keyL, 0, PASSWD_LEN);
517 strncpy(reinterpret_cast<char*>(keyL), password.c_str(), PASSWD_LEN);
518 Blowfish_Init(&ctx, keyL, PASSWD_LEN);
520 //-----------------------------------------------------------------------------
521 void REMOTE_SCRIPT::Encrypt(void * dst, const void * src, size_t len8) const
524 memcpy(dst, src, len8 * 8);
525 for (size_t i = 0; i < len8; ++i)
526 Blowfish_Encrypt(&ctx, static_cast<uint32_t *>(dst) + i * 2, static_cast<uint32_t *>(dst) + i * 2 + 1);
528 //-----------------------------------------------------------------------------