y_flooding.inc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #if defined _INC_y_flooding
  2. #endinput
  3. #endif
  4. #define _INC_y_flooding
  5. /**
  6. * <library name="y_flooding">
  7. * <section>
  8. * Description
  9. * </section>
  10. * Allows a limited number of connections from a single IP.
  11. * <section>
  12. * Functions
  13. * </section>
  14. * <subsection>
  15. * Core
  16. * </subsection><ul>
  17. * <symbol name="OnPlayerConnect">Called to check IPs.</symbol>
  18. * <symbol name="OnScriptInit">Sets the OnPlayerConnect function flag.</symbol>
  19. * </ul><subsection>
  20. * API
  21. * </subsection><ul>
  22. * <symbol name="SetMaxConnections">Sets the max allowed connections from an IP.</symbol>
  23. * </ul><section>
  24. * Enums
  25. * </section><ul>
  26. * <symbol name="e_FLOOD_ACTION">What to do if too many connections form.</symbol>
  27. * </ul><section>
  28. * Variables
  29. * </section>
  30. * <subsection>
  31. * Static
  32. * </subsection><ul>
  33. * <symbol name="YSI_g_sPlayerIPs">People's stored IPs for speed.</symbol>
  34. * <symbol name="YSI_g_sMaxConnections">Data for the script.</symbol>
  35. * </ul>
  36. * </library>
  37. *//** *//*
  38. Legal:
  39. Version: MPL 1.1
  40. The contents of this file are subject to the Mozilla Public License Version
  41. 1.1 the "License"; you may not use this file except in compliance with
  42. the License. You may obtain a copy of the License at
  43. http://www.mozilla.org/MPL/
  44. Software distributed under the License is distributed on an "AS IS" basis,
  45. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  46. for the specific language governing rights and limitations under the
  47. License.
  48. The Original Code is the YSI framework.
  49. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  50. Portions created by the Initial Developer are Copyright C 2011
  51. the Initial Developer. All Rights Reserved.
  52. Contributors:
  53. Y_Less
  54. koolk
  55. JoeBullet/Google63
  56. g_aSlice/Slice
  57. Misiur
  58. samphunter
  59. tianmeta
  60. maddinat0r
  61. spacemud
  62. Crayder
  63. Dayvison
  64. Ahmad45123
  65. Zeex
  66. irinel1996
  67. Yiin-
  68. Chaprnks
  69. Konstantinos
  70. Masterchen09
  71. Southclaws
  72. PatchwerkQWER
  73. m0k1
  74. paulommu
  75. udan111
  76. Thanks:
  77. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  78. ZeeX - Very productive conversations.
  79. koolk - IsPlayerinAreaEx code.
  80. TheAlpha - Danish translation.
  81. breadfish - German translation.
  82. Fireburn - Dutch translation.
  83. yom - French translation.
  84. 50p - Polish translation.
  85. Zamaroht - Spanish translation.
  86. Los - Portuguese translation.
  87. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  88. me to strive to better.
  89. Pixels^ - Running XScripters where the idea was born.
  90. Matite - Pestering me to release it and using it.
  91. Very special thanks to:
  92. Thiadmer - PAWN, whose limits continue to amaze me!
  93. Kye/Kalcor - SA:MP.
  94. SA:MP Team past, present and future - SA:MP.
  95. Optional plugins:
  96. Gamer_Z - GPS.
  97. Incognito - Streamer.
  98. Me - sscanf2, fixes2, Whirlpool.
  99. */
  100. #include "..\YSI_Internal\y_version"
  101. #include "..\YSI_Data\y_iterate"
  102. #include "..\YSI_Core\y_debug"
  103. #include "..\YSI_Core\y_utils"
  104. #include "..\YSI_Coding\y_hooks"
  105. enum e_FLOOD_ACTION (+= 0x00010000)
  106. {
  107. e_FLOOD_ACTION_COUNT = 0x0000FFFF,
  108. e_FLOOD_ACTION_ACTION = 0x000F0000,
  109. e_FLOOD_ACTION_NOTHING = 0,
  110. e_FLOOD_ACTION_BLOCK,
  111. e_FLOOD_ACTION_KICK,
  112. e_FLOOD_ACTION_BAN,
  113. e_FLOOD_ACTION_FBAN,
  114. e_FLOOD_ACTION_GHOST,
  115. e_FLOOD_ACTION_OTHER
  116. }
  117. static
  118. YSI_g_sPlayerIPs[MAX_PLAYERS],
  119. e_FLOOD_ACTION:YSI_g_sMaxConnections = e_FLOOD_ACTION_COUNT | e_FLOOD_ACTION_BLOCK;
  120. forward OnFloodLimitExceeded(ip[16], count);
  121. stock
  122. Iterator:FloodingPlayer<MAX_PLAYERS>;
  123. /*-------------------------------------------------------------------------*//**
  124. * <param name="max">Maximum number of connections allowed from the same IP.</param>
  125. * <param name="action">What to do if there's too many.</param>
  126. * <remarks>
  127. * Sets the maximum connections allowed from a single IP.
  128. *
  129. * Options:
  130. *
  131. * e_FLOOD_ACTION_BLOCK - Kick the latest player on this IP.
  132. * e_FLOOD_ACTION_KICK - Kick all players on this IP.
  133. * e_FLOOD_ACTION_BAN - Ban the IP and have players time out.
  134. * e_FLOOD_ACTION_FBAN - Ban the IP and kick all the players instantly.
  135. * e_FLOOD_ACTION_GHOST - Silently force all players on the IP to reconnect.
  136. * e_FLOOD_ACTION_OTHER - Call a callback.
  137. * </remarks>
  138. *//*------------------------------------------------------------------------**/
  139. stock SetMaxConnections(max = -1, e_FLOOD_ACTION:action = e_FLOOD_ACTION_BLOCK)
  140. {
  141. P:3("SetMaxConnections called: %i, %i", max, _:action);
  142. YSI_g_sMaxConnections = (e_FLOOD_ACTION:max & e_FLOOD_ACTION_COUNT) | action;
  143. }
  144. /*-------------------------------------------------------------------------*//**
  145. * <param name="ip32">32-bit representation of the IP to unban.</param>
  146. * <remarks>
  147. * Timers, by default, are not good with strings, so we can't pass the IP to
  148. * unban in dot notation. Fortunately, this is easilly solved.
  149. * </remarks>
  150. *//*------------------------------------------------------------------------**/
  151. forward Flooding_UnbanIP(ip32);
  152. public Flooding_UnbanIP(ip32)
  153. {
  154. new
  155. cmd[24] = "unbanip ";
  156. format(cmd[8], 16, "%d.%d.%d.%d", ip32 >>> 24, (ip32 >>> 16) & 0xFF, (ip32 >>> 8) & 0xFF, ip32 & 0xFF);
  157. SendRconCommand(cmd);
  158. }
  159. /*-------------------------------------------------------------------------*//**
  160. * <param name="playerid">Player who joined.</param>
  161. * <remarks>
  162. * Checks for too many connections from the same IP address and acts
  163. * accordingly.
  164. *
  165. * Could be edited to only loop through players once but I'm not sure the
  166. * extra code required would be faster anyway, definately not easier.
  167. * </remarks>
  168. *//*------------------------------------------------------------------------**/
  169. hook OnPlayerConnect(playerid)
  170. {
  171. new
  172. ret = 1;
  173. if ((YSI_g_sMaxConnections & e_FLOOD_ACTION_COUNT) != e_FLOOD_ACTION_COUNT)
  174. {
  175. new
  176. ip[16];
  177. GetPlayerIp(playerid, ip, sizeof (ip));
  178. new
  179. ip32 = IPToInt(ip);
  180. YSI_g_sPlayerIPs[playerid] = ip32;
  181. foreach (new i : Player)
  182. {
  183. if (YSI_g_sPlayerIPs[i] == ip32)
  184. {
  185. Iter_Add(FloodingPlayer, i);
  186. }
  187. }
  188. if (Iter_Count(FloodingPlayer) > _:(YSI_g_sMaxConnections & e_FLOOD_ACTION_COUNT))
  189. {
  190. P:I("Max Connections exceeded");
  191. ret = 0;
  192. switch (YSI_g_sMaxConnections & e_FLOOD_ACTION_ACTION)
  193. {
  194. case e_FLOOD_ACTION_BLOCK:
  195. {
  196. // Kick the latest player.
  197. Kick(playerid);
  198. }
  199. case e_FLOOD_ACTION_KICK:
  200. {
  201. // Kick all the players.
  202. foreach (new i : FloodingPlayer)
  203. {
  204. Kick(i);
  205. }
  206. }
  207. case e_FLOOD_ACTION_BAN:
  208. {
  209. // Ban the IP.
  210. BanEx(playerid, "YSI max connections auto-ban");
  211. }
  212. case e_FLOOD_ACTION_FBAN:
  213. {
  214. // Ban the IP.
  215. BanEx(playerid, "YSI max connections auto-ban");
  216. // Kick all the players.
  217. foreach (new i : FloodingPlayer)
  218. {
  219. Kick(i);
  220. }
  221. }
  222. case e_FLOOD_ACTION_GHOST:
  223. {
  224. // Time out all the players on the IP silently.
  225. new
  226. cmd[22] = "banip ";
  227. strcat(cmd, ip);
  228. SendRconCommand(cmd);
  229. SetTimerEx("Flooding_UnbanIP", 10000, 0, "i", ip32);
  230. }
  231. case e_FLOOD_ACTION_OTHER:
  232. {
  233. ret = CallLocalFunction("OnFloodLimitExceeded", "si", ip, Iter_Count(FloodingPlayer));
  234. }
  235. }
  236. }
  237. // Ultra fast iterator clear.
  238. for (new i = Iter_Begin(FloodingPlayer); (ip32 = Iter_Next(FloodingPlayer, i)) != i; )
  239. {
  240. Iter_TrueArray(FloodingPlayer)[i] = i;
  241. i = ip32;
  242. }
  243. Iter_TrueCount(FloodingPlayer) = 0;
  244. }
  245. return ret;
  246. }