login.c 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931
  1. // $Id: login.c,v 1.6 2004/09/19 21:12:07 Valaris Exp $
  2. // original : login2.c 2003/01/28 02:29:17 Rev.1.1.1.1
  3. // txt version 1.100
  4. #include <sys/types.h>
  5. #ifdef LCCWIN32
  6. #include <winsock.h>
  7. #pragma lib <libmysql.lib>
  8. #else
  9. #ifdef WIN32
  10. #define WIN32_LEAN_AND_MEAN
  11. #include <windows.h>
  12. #include <winsock2.h>
  13. #include <time.h>
  14. void Gettimeofday(struct timeval *timenow)
  15. {
  16. time_t t;
  17. t = clock();
  18. timenow->tv_usec = t;
  19. timenow->tv_sec = t / CLK_TCK;
  20. return;
  21. }
  22. #define gettimeofday(timenow, dummy) Gettimeofday(timenow)
  23. #pragma comment(lib,"libmysql.lib")
  24. #else
  25. #include <sys/socket.h>
  26. #include <netinet/in.h>
  27. #include <sys/time.h>
  28. #include <sys/ioctl.h>
  29. #include <arpa/inet.h>
  30. #include <netdb.h>
  31. #include <unistd.h>
  32. #endif
  33. #endif
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <time.h>
  37. #include <sys/stat.h> // for stat/lstat/fstat
  38. #include <signal.h>
  39. #include <fcntl.h>
  40. #include <string.h>
  41. #include "malloc.h"
  42. //add include for DBMS(mysql)
  43. #include <mysql.h>
  44. #include "../common/strlib.h"
  45. #include "timer.h"
  46. /*
  47. #include "timer.h"
  48. #include "core.h"
  49. #include "socket.h"
  50. #include "login.h"
  51. #include "mmo.h"
  52. #include "version.h"
  53. #include "db.h"
  54. */
  55. #include "../common/core.h"
  56. #include "../common/socket.h"
  57. #include "login.h"
  58. #include "../common/mmo.h"
  59. #include "../common/version.h"
  60. #include "../common/db.h"
  61. #include "../common/timer.h"
  62. #ifdef PASSWORDENC
  63. #include "md5calc.h"
  64. #endif
  65. #ifdef MEMWATCH
  66. #include "memwatch.h"
  67. #endif
  68. #define J_MAX_MALLOC_SIZE 65535
  69. //-----------------------------------------------------
  70. // global variable
  71. //-----------------------------------------------------
  72. int account_id_count = START_ACCOUNT_NUM;
  73. int server_num;
  74. int new_account_flag = 0; //Set from config too XD [Sirius]
  75. char bind_ip_str[16];
  76. in_addr_t bind_ip;
  77. int login_port = 6900;
  78. char lan_char_ip[128]; // Lan char ip added by kashy
  79. int subnetmaski[4]; // Subnetmask added by kashy
  80. struct mmo_char_server server[MAX_SERVERS];
  81. int server_fd[MAX_SERVERS];
  82. int server_freezeflag[MAX_SERVERS]; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
  83. int anti_freeze_enable = 0;
  84. int ANTI_FREEZE_INTERVAL = 15;
  85. int login_fd;
  86. //Added for Mugendai's I'm Alive mod
  87. int imalive_on=0;
  88. int imalive_time=60;
  89. //Added by Mugendai for GUI
  90. int flush_on=1;
  91. int flush_time=100;
  92. char date_format[32] = "%Y-%m-%d %H:%M:%S";
  93. int auth_num = 0, auth_max = 0;
  94. int min_level_to_connect = 0; // minimum level of player/GM (0: player, 1-99: gm) to connect on the server
  95. int check_ip_flag = 1; // It's to check IP of a player between login-server and char-server (part of anti-hacking system)
  96. int check_client_version = 0; //Client version check ON/OFF .. (sirius)
  97. int client_version_to_connect = 20; //Client version needed to connect ..(sirius)
  98. MYSQL mysql_handle;
  99. int ipban = 1;
  100. int dynamic_account_ban = 1;
  101. int dynamic_account_ban_class = 0;
  102. int dynamic_pass_failure_ban = 1;
  103. int dynamic_pass_failure_ban_time = 5;
  104. int dynamic_pass_failure_ban_how_many = 3;
  105. int dynamic_pass_failure_ban_how_long = 60;
  106. int login_server_port = 3306;
  107. char login_server_ip[32] = "127.0.0.1";
  108. char login_server_id[32] = "ragnarok";
  109. char login_server_pw[32] = "ragnarok";
  110. char login_server_db[32] = "ragnarok";
  111. int use_md5_passwds = 0;
  112. char login_db[256] = "login";
  113. char loginlog_db[256] = "loginlog";
  114. // added to help out custom login tables, without having to recompile
  115. // source so options are kept in the login_athena.conf or the inter_athena.conf
  116. char login_db_account_id[256] = "account_id";
  117. char login_db_userid[256] = "userid";
  118. char login_db_user_pass[256] = "user_pass";
  119. char login_db_level[256] = "level";
  120. char tmpsql[65535], tmp_sql[65535];
  121. int console = 0;
  122. int case_sensitive = 1;
  123. //-----------------------------------------------------
  124. #define AUTH_FIFO_SIZE 256
  125. struct {
  126. int account_id,login_id1,login_id2;
  127. int ip,sex,delflag;
  128. } auth_fifo[AUTH_FIFO_SIZE];
  129. int auth_fifo_pos = 0;
  130. //-----------------------------------------------------
  131. static char md5key[20], md5keylen = 16;
  132. struct dbt *online_db;
  133. //-----------------------------------------------------
  134. // Online User Database [Wizputer]
  135. //-----------------------------------------------------
  136. void add_online_user(int account_id) {
  137. int *p;
  138. p = (int*)aMalloc(sizeof(int));
  139. if (p == NULL) {
  140. printf("add_online_user: memory allocation failure (malloc)!\n");
  141. exit(0);
  142. }
  143. *p = account_id;
  144. numdb_insert(online_db, account_id, p);
  145. }
  146. int is_user_online(int account_id) {
  147. int *p;
  148. p = (int*)numdb_search(online_db, account_id);
  149. if (p == NULL)
  150. return 0;
  151. printf("Acccount %d\n",*p);
  152. return 1;
  153. }
  154. void remove_online_user(int account_id) {
  155. int *p;
  156. p = (int*)numdb_erase(online_db,account_id);
  157. aFree(p);
  158. }
  159. //-----------------------------------------------------
  160. // check user level
  161. //-----------------------------------------------------
  162. int isGM(int account_id) {
  163. int level;
  164. MYSQL_RES* sql_res;
  165. MYSQL_ROW sql_row;
  166. level = 0;
  167. sprintf(tmpsql,"SELECT `%s` FROM `%s` WHERE `%s`='%d'", login_db_level, login_db, login_db_account_id, account_id);
  168. if (mysql_query(&mysql_handle, tmpsql)) {
  169. printf("DB server Error (select GM Level to Memory)- %s\n", mysql_error(&mysql_handle));
  170. }
  171. sql_res = mysql_store_result(&mysql_handle);
  172. if (sql_res) {
  173. sql_row = mysql_fetch_row(sql_res);
  174. level = atoi(sql_row[0]);
  175. if (level > 99)
  176. level = 99;
  177. }
  178. if (level == 0) {
  179. return 0;
  180. //not GM
  181. }
  182. mysql_free_result(sql_res);
  183. return level;
  184. }
  185. //-----------------------------------------------------
  186. // Function to suppress control characters in a string.
  187. //-----------------------------------------------------
  188. int remove_control_chars(unsigned char *str) {
  189. int i;
  190. int change = 0;
  191. for(i = 0; str[i]; i++) {
  192. if (str[i] < 32) {
  193. str[i] = '_';
  194. change = 1;
  195. }
  196. }
  197. return change;
  198. }
  199. //---------------------------------------------------
  200. // E-mail check: return 0 (not correct) or 1 (valid).
  201. //---------------------------------------------------
  202. int e_mail_check(char *email) {
  203. char ch;
  204. char* last_arobas;
  205. // athena limits
  206. if (strlen(email) < 3 || strlen(email) > 39)
  207. return 0;
  208. // part of RFC limits (official reference of e-mail description)
  209. if (strchr(email, '@') == NULL || email[strlen(email)-1] == '@')
  210. return 0;
  211. if (email[strlen(email)-1] == '.')
  212. return 0;
  213. last_arobas = strrchr(email, '@');
  214. if (strstr(last_arobas, "@.") != NULL ||
  215. strstr(last_arobas, "..") != NULL)
  216. return 0;
  217. for(ch = 1; ch < 32; ch++) {
  218. if (strchr(last_arobas, ch) != NULL) {
  219. return 0;
  220. break;
  221. }
  222. }
  223. if (strchr(last_arobas, ' ') != NULL ||
  224. strchr(last_arobas, ';') != NULL)
  225. return 0;
  226. // all correct
  227. return 1;
  228. }
  229. //-----------------------------------------------------
  230. // Read Account database - mysql db
  231. //-----------------------------------------------------
  232. int mmo_auth_sqldb_init(void) {
  233. printf("Login server init....\n");
  234. // memory initialize
  235. printf("memory initialize....\n");
  236. mysql_init(&mysql_handle);
  237. // DB connection start
  238. printf("Connect Login Database Server....\n");
  239. if (!mysql_real_connect(&mysql_handle, login_server_ip, login_server_id, login_server_pw,
  240. login_server_db, login_server_port, (char *)NULL, 0)) {
  241. // pointer check
  242. printf("%s\n", mysql_error(&mysql_handle));
  243. exit(1);
  244. } else {
  245. printf("connect success!\n");
  246. }
  247. sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver', '100','login server started')", loginlog_db);
  248. //query
  249. if (mysql_query(&mysql_handle, tmpsql)) {
  250. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  251. }
  252. return 0;
  253. }
  254. //-----------------------------------------------------
  255. // DB server connect check
  256. //-----------------------------------------------------
  257. void mmo_auth_sqldb_sync(void) {
  258. // db connect check? or close?
  259. // ping pong DB server -if losted? then connect try. else crash.
  260. }
  261. //-----------------------------------------------------
  262. // close DB
  263. //-----------------------------------------------------
  264. void mmo_db_close(void) {
  265. int i, fd;
  266. //set log.
  267. sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '', 'lserver','100', 'login server shutdown')", loginlog_db);
  268. //query
  269. if (mysql_query(&mysql_handle, tmpsql)) {
  270. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  271. }
  272. //delete all server status
  273. sprintf(tmpsql,"DELETE FROM `sstatus`");
  274. //query
  275. if (mysql_query(&mysql_handle, tmpsql)) {
  276. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  277. }
  278. mysql_close(&mysql_handle);
  279. printf("close DB connect....\n");
  280. for (i = 0; i < MAX_SERVERS; i++) {
  281. if ((fd = server_fd[i]) >= 0)
  282. delete_session(fd);
  283. }
  284. delete_session(login_fd);
  285. }
  286. //-----------------------------------------------------
  287. // Make new account
  288. //-----------------------------------------------------
  289. int mmo_auth_sqldb_new(struct mmo_account* account,const char *tmpstr, char sex) {
  290. //no need on DB version
  291. printf("Request new account.... - not support on this version\n");
  292. return 0;
  293. }
  294. //-----------------------------------------------------
  295. // Make new account
  296. //-----------------------------------------------------
  297. int mmo_auth_new(struct mmo_account* account, const char *tmpstr, char sex) {
  298. return 0;
  299. }
  300. #ifdef LCCWIN32
  301. extern void gettimeofday(struct timeval *t, struct timezone *dummy);
  302. #endif
  303. //-----------------------------------------------------
  304. // Auth
  305. //-----------------------------------------------------
  306. int mmo_auth( struct mmo_account* account , int fd){
  307. struct timeval tv;
  308. time_t ban_until_time;
  309. char tmpstr[256];
  310. char t_uid[256], t_pass[256];
  311. char user_password[256];
  312. //added for account creation _M _F
  313. int len;
  314. MYSQL_RES* sql_res;
  315. MYSQL_ROW sql_row;
  316. //int sql_fields, sql_cnt;
  317. char md5str[64], md5bin[32];
  318. char ip[16];
  319. unsigned char *sin_addr = (unsigned char *)&session[fd]->client_addr.sin_addr;
  320. printf ("auth start...\n");
  321. sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
  322. //accountreg with _M/_F .. [Sirius]
  323. len = strlen(account->userid) -2;
  324. if (account->passwdenc == 0 && account->userid[len] == '_' &&
  325. (account->userid[len+1] == 'F' || account->userid[len+1] == 'M') && new_account_flag == 1 &&
  326. account_id_count <= END_ACCOUNT_NUM && len >= 4 && strlen(account->passwd) >= 4) {
  327. if (new_account_flag == 1)
  328. account->userid[len] = '\0';
  329. sprintf(tmp_sql, "SELECT `%s` FROM `%s` WHERE `userid` = '%s'", login_db_userid, login_db, account->userid);
  330. if(mysql_query(&mysql_handle, tmp_sql)){
  331. printf("SQL error (_M/_F reg): %s", mysql_error(&mysql_handle));
  332. }else{
  333. sql_res = mysql_store_result(&mysql_handle);
  334. if(mysql_num_rows(sql_res) == 0){
  335. //ok no existing acc,
  336. printf("Adding a new account user: %s with passwd: %s sex: %c (ip: %s)\n", account->userid, account->passwd, account->userid[len+1], ip);
  337. sprintf(tmp_sql, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`) VALUES ('%s', '%s', '%c', '%s')", login_db, login_db_userid, login_db_user_pass, account->userid, account->passwd, account->userid[len+1], "a@a.com");
  338. if(mysql_query(&mysql_handle, tmp_sql)){
  339. //Failed to insert new acc :/
  340. printf("SQL Error (_M/_F reg) .. insert ..: %s", mysql_error(&mysql_handle));
  341. }//sql query check to insert
  342. }//rownum check (0!)
  343. mysql_free_result(sql_res);
  344. }//sqlquery
  345. }//all values for NEWaccount ok ?
  346. // auth start : time seed
  347. gettimeofday(&tv, NULL);
  348. strftime(tmpstr, 24, "%Y-%m-%d %H:%M:%S",localtime((const time_t*)&(tv.tv_sec)));
  349. sprintf(tmpstr+19, ".%03d", (int)tv.tv_usec/1000);
  350. jstrescapecpy(t_uid,account->userid);
  351. jstrescapecpy(t_pass, account->passwd);
  352. //check for lasted version (exe version check) [Sirius]
  353. if(check_client_version == 1){
  354. if(account->version != client_version_to_connect){
  355. return 6;
  356. }
  357. }
  358. // make query
  359. sprintf(tmpsql, "SELECT `%s`,`%s`,`%s`,`lastlogin`,`logincount`,`sex`,`connect_until`,`last_ip`,`ban_until`,`state`,`%s`"
  360. " FROM `%s` WHERE %s `%s`='%s'", login_db_account_id, login_db_userid, login_db_user_pass, login_db_level, login_db, case_sensitive ? "BINARY" : "", login_db_userid, t_uid);
  361. //login {0-account_id/1-userid/2-user_pass/3-lastlogin/4-logincount/5-sex/6-connect_untl/7-last_ip/8-ban_until/9-state}
  362. // query
  363. if (mysql_query(&mysql_handle, tmpsql)) {
  364. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  365. }
  366. sql_res = mysql_store_result(&mysql_handle) ;
  367. if (sql_res) {
  368. sql_row = mysql_fetch_row(sql_res); //row fetching
  369. if (!sql_row) {
  370. //there's no id.
  371. printf ("auth failed no account %s %s %s\n", tmpstr, account->userid, account->passwd);
  372. mysql_free_result(sql_res);
  373. return 0;
  374. }
  375. } else {
  376. printf("mmo_auth DB result error ! \n");
  377. return 0;
  378. }
  379. // Documented by CLOWNISIUS || LLRO || Gunstar lead this one with me
  380. // IF changed to diferent returns~ you get diferent responses from your msgstringtable.txt
  381. //Ireturn 2 == line 9
  382. //Ireturn 5 == line 311
  383. //Ireturn 6 == line 450
  384. //Ireturn 7 == line 440
  385. //Ireturn 8 == line 682
  386. //Ireturn 9 == line 704
  387. //Ireturn 10 == line 705
  388. //Ireturn 11 == line 706
  389. //Ireturn 12 == line 707
  390. //Ireturn 13 == line 708
  391. //Ireturn 14 == line 709
  392. //Ireturn 15 == line 710
  393. //Ireturn -1 == line 010
  394. // Check status
  395. {
  396. int encpasswdok = 0;
  397. if (atoi(sql_row[9]) == -3) {
  398. //id is banned
  399. mysql_free_result(sql_res);
  400. return -3;
  401. } else if (atoi(sql_row[9]) == -2) { //dynamic ban
  402. //id is banned
  403. mysql_free_result(sql_res);
  404. //add IP list.
  405. return -2;
  406. }
  407. if (use_md5_passwds) {
  408. MD5_String(account->passwd,user_password);
  409. } else {
  410. jstrescapecpy(user_password, account->passwd);
  411. }
  412. printf("account id ok encval:%d\n",account->passwdenc);
  413. #ifdef PASSWORDENC
  414. if (account->passwdenc > 0) {
  415. int j = account->passwdenc;
  416. printf ("start md5calc..\n");
  417. if (j > 2)
  418. j = 1;
  419. do {
  420. if (j == 1) {
  421. sprintf(md5str, "%s%s", md5key,sql_row[2]);
  422. } else if (j == 2) {
  423. sprintf(md5str, "%s%s", sql_row[2], md5key);
  424. } else
  425. md5str[0] = 0;
  426. printf("j:%d mdstr:%s\n", j, md5str);
  427. MD5_String2binary(md5str, md5bin);
  428. encpasswdok = (memcmp(user_password, md5bin, 16) == 0);
  429. } while (j < 2 && !encpasswdok && (j++) != account->passwdenc);
  430. //printf("key[%s] md5 [%s] ", md5key, md5);
  431. printf("client [%s] accountpass [%s]\n", user_password, sql_row[2]);
  432. printf ("end md5calc..\n");
  433. }
  434. #endif
  435. if ((strcmp(user_password, sql_row[2]) && !encpasswdok)) {
  436. if (account->passwdenc == 0) {
  437. printf ("auth failed pass error %s %s %s" RETCODE, tmpstr, account->userid, user_password);
  438. #ifdef PASSWORDENC
  439. } else {
  440. char logbuf[1024], *p = logbuf;
  441. int j;
  442. p += sprintf(p, "auth failed pass error %s %s recv-md5[", tmpstr, account->userid);
  443. for(j = 0; j < 16; j++)
  444. p += sprintf(p, "%02x", ((unsigned char *)user_password)[j]);
  445. p += sprintf(p, "] calc-md5[");
  446. for(j = 0; j < 16; j++)
  447. p += sprintf(p, "%02x", ((unsigned char *)md5bin)[j]);
  448. p += sprintf(p, "] md5key[");
  449. for(j = 0; j < md5keylen; j++)
  450. p += sprintf(p, "%02x", ((unsigned char *)md5key)[j]);
  451. p += sprintf(p, "]" RETCODE);
  452. printf("%s\n", p);
  453. #endif
  454. }
  455. return 1;
  456. }
  457. printf("auth ok %s %s" RETCODE, tmpstr, account->userid);
  458. }
  459. if (atoi(sql_row[9])) {
  460. switch(atoi(sql_row[9])) { // packet 0x006a value + 1
  461. case 1: // 0 = Unregistered ID
  462. case 2: // 1 = Incorrect Password
  463. case 3: // 2 = This ID is expired
  464. case 4: // 3 = Rejected from Server
  465. case 5: // 4 = You have been blocked by the GM Team
  466. case 6: // 5 = Your Game's EXE file is not the latest version
  467. case 7: // 6 = Your are Prohibited to log in until %s
  468. case 8: // 7 = Server is jammed due to over populated
  469. case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
  470. case 100: // 99 = This ID has been totally erased
  471. printf("Auth Error #%d\n", atoi(sql_row[9]));
  472. return atoi(sql_row[9]) - 1;
  473. break;
  474. default:
  475. return 99; // 99 = ID has been totally erased
  476. break;
  477. }
  478. }
  479. /*
  480. // do not remove this section. this is meant for future, and current forums usage
  481. // as a login manager and CP for login server. [CLOWNISIUS]
  482. if (atoi(sql_row[10]) == 1) {
  483. return 4;
  484. }
  485. if (atoi(sql_row[10]) >= 5) {
  486. switch(atoi(sql_row[10])) {
  487. case 5:
  488. return 5;
  489. break;
  490. case 6:
  491. return 7;
  492. break;
  493. case 7:
  494. return 9;
  495. break;
  496. case 8:
  497. return 10;
  498. break;
  499. case 9:
  500. return 11;
  501. break;
  502. default:
  503. return 10;
  504. break;
  505. }
  506. }
  507. */
  508. ban_until_time = atol(sql_row[8]);
  509. //login {0-account_id/1-userid/2-user_pass/3-lastlogin/4-logincount/5-sex/6-connect_untl/7-last_ip/8-ban_until/9-state}
  510. if (ban_until_time != 0) { // if account is banned
  511. strftime(tmpstr, 20, date_format, localtime(&ban_until_time));
  512. tmpstr[19] = '\0';
  513. if (ban_until_time > time(NULL)) { // always banned
  514. return 6; // 6 = Your are Prohibited to log in until %s
  515. } else { // ban is finished
  516. // reset the ban time
  517. sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0' WHERE %s `%s`='%s'", login_db, case_sensitive ? "BINARY" : "", login_db_userid, t_uid);
  518. if (mysql_query(&mysql_handle, tmpsql)) {
  519. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  520. }
  521. }
  522. }
  523. if (atol(sql_row[6]) != 0 && atol(sql_row[6]) < time(NULL)) {
  524. return 2; // 2 = This ID is expired
  525. }
  526. if ( is_user_online(atol(sql_row[0])) ) {
  527. printf("User [%s] is already online - Rejected.\n",sql_row[1]);
  528. #ifndef TWILIGHT
  529. return 3; // Rejected
  530. #endif
  531. }
  532. account->account_id = atoi(sql_row[0]);
  533. account->login_id1 = rand();
  534. account->login_id2 = rand();
  535. memcpy(tmpstr, sql_row[3], 19);
  536. memcpy(account->lastlogin, tmpstr, 24);
  537. account->sex = sql_row[5][0] == 'S' ? 2 : sql_row[5][0]=='M';
  538. sprintf(tmpsql, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount` +1, `last_ip`='%s' WHERE %s `%s` = '%s'",
  539. login_db, ip, case_sensitive ? "BINARY" : "", login_db_userid, sql_row[1]);
  540. mysql_free_result(sql_res) ; //resource free
  541. if (mysql_query(&mysql_handle, tmpsql)) {
  542. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  543. }
  544. return -1;
  545. }
  546. // Send to char
  547. int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) {
  548. int i, c;
  549. int fd;
  550. c = 0;
  551. for(i = 0; i < MAX_SERVERS; i++) {
  552. if ((fd = server_fd[i]) > 0 && fd != sfd) {
  553. memcpy(WFIFOP(fd,0), buf, len);
  554. WFIFOSET(fd,len);
  555. c++;
  556. }
  557. }
  558. return c;
  559. }
  560. //--------------------------------
  561. // Char-server anti-freeze system
  562. //--------------------------------
  563. int char_anti_freeze_system(int tid, unsigned int tick, int id, int data) {
  564. int i;
  565. for(i = 0; i < MAX_SERVERS; i++) {
  566. if (server_fd[i] >= 0) {// if char-server is online
  567. // printf("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]);
  568. if (server_freezeflag[i]-- < 1) {// Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
  569. session[server_fd[i]]->eof = 1;
  570. } else {
  571. // send alive packet to check connection
  572. WFIFOW(server_fd[i],0) = 0x2718;
  573. WFIFOSET(server_fd[i],2);
  574. }
  575. }
  576. }
  577. return 0;
  578. }
  579. //-----------------------------------------------------
  580. // char-server packet parse
  581. //-----------------------------------------------------
  582. int parse_fromchar(int fd){
  583. int i, id;
  584. MYSQL_RES* sql_res;
  585. MYSQL_ROW sql_row = NULL;
  586. unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
  587. char ip[16];
  588. sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  589. for(id = 0; id < MAX_SERVERS; id++)
  590. if (server_fd[id] == fd)
  591. break;
  592. if (id == MAX_SERVERS)
  593. session[fd]->eof = 1;
  594. if(session[fd]->eof) {
  595. if (id < MAX_SERVERS) {
  596. printf("Char-server '%s' has disconnected.\n", server[id].name);
  597. server_fd[id] = -1;
  598. memset(&server[id], 0, sizeof(struct mmo_char_server));
  599. // server delete
  600. sprintf(tmpsql, "DELETE FROM `sstatus` WHERE `index`='%d'", id);
  601. // query
  602. if (mysql_query(&mysql_handle, tmpsql)) {
  603. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  604. }
  605. }
  606. close(fd);
  607. delete_session(fd);
  608. return 0;
  609. }
  610. while(RFIFOREST(fd) >= 2) {
  611. // printf("char_parse: %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0));
  612. switch (RFIFOW(fd,0)) {
  613. case 0x2712:
  614. if (RFIFOREST(fd) < 19)
  615. return 0;
  616. {
  617. int account_id;
  618. account_id = RFIFOL(fd,2); // speed up
  619. for(i=0;i<AUTH_FIFO_SIZE;i++){
  620. if (auth_fifo[i].account_id == account_id &&
  621. auth_fifo[i].login_id1 == RFIFOL(fd,6) &&
  622. #if CMP_AUTHFIFO_LOGIN2 != 0
  623. auth_fifo[i].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18
  624. #endif
  625. auth_fifo[i].sex == RFIFOB(fd,14) &&
  626. #if CMP_AUTHFIFO_IP != 0
  627. auth_fifo[i].ip == RFIFOL(fd,15) &&
  628. #endif
  629. !auth_fifo[i].delflag) {
  630. auth_fifo[i].delflag = 1;
  631. printf("auth -> %d\n", i);
  632. break;
  633. }
  634. }
  635. if (i != AUTH_FIFO_SIZE) { // send account_reg
  636. int p;
  637. time_t connect_until_time = 0;
  638. char email[40] = "";
  639. account_id=RFIFOL(fd,2);
  640. sprintf(tmpsql, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id);
  641. if (mysql_query(&mysql_handle, tmpsql)) {
  642. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  643. }
  644. sql_res = mysql_store_result(&mysql_handle) ;
  645. if (sql_res) {
  646. sql_row = mysql_fetch_row(sql_res);
  647. connect_until_time = atol(sql_row[1]);
  648. strcpy(email, sql_row[0]);
  649. }
  650. mysql_free_result(sql_res);
  651. if (account_id > 0) {
  652. sprintf(tmpsql, "SELECT `str`,`value` FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d'",account_id);
  653. if (mysql_query(&mysql_handle, tmpsql)) {
  654. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  655. }
  656. sql_res = mysql_store_result(&mysql_handle) ;
  657. if (sql_res) {
  658. WFIFOW(fd,0) = 0x2729;
  659. WFIFOL(fd,4) = account_id;
  660. for(p = 8; (sql_row = mysql_fetch_row(sql_res));p+=36){
  661. memcpy(WFIFOP(fd,p), sql_row[0], 32);
  662. WFIFOL(fd,p+32) = atoi(sql_row[1]);
  663. }
  664. WFIFOW(fd,2) = p;
  665. WFIFOSET(fd,p);
  666. //printf("account_reg2 send : login->char (auth fifo)\n");
  667. WFIFOW(fd,0) = 0x2713;
  668. WFIFOL(fd,2) = account_id;
  669. WFIFOB(fd,6) = 0;
  670. memcpy(WFIFOP(fd, 7), email, 40);
  671. WFIFOL(fd,47) = (unsigned long) connect_until_time;
  672. WFIFOSET(fd,51);
  673. }
  674. mysql_free_result(sql_res);
  675. }
  676. } else {
  677. WFIFOW(fd,0) = 0x2713;
  678. WFIFOL(fd,2) = account_id;
  679. WFIFOB(fd,6) = 1;
  680. WFIFOSET(fd,51);
  681. }
  682. }
  683. RFIFOSKIP(fd,19);
  684. break;
  685. case 0x2714:
  686. if (RFIFOREST(fd) < 6)
  687. return 0;
  688. // how many users on world? (update)
  689. if (server[id].users != RFIFOL(fd,2))
  690. printf("set users %s : %d\n", server[id].name, RFIFOL(fd,2));
  691. server[id].users = RFIFOL(fd,2);
  692. if(anti_freeze_enable)
  693. server_freezeflag[id] = 5; // Char anti-freeze system. Counter. 5 ok, 4...0 freezed
  694. sprintf(tmpsql,"UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id);
  695. // query
  696. if (mysql_query(&mysql_handle, tmpsql)) {
  697. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  698. }
  699. RFIFOSKIP(fd,6);
  700. break;
  701. // We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server
  702. case 0x2716:
  703. if (RFIFOREST(fd) < 6)
  704. return 0;
  705. {
  706. int account_id;
  707. time_t connect_until_time = 0;
  708. char email[40] = "";
  709. account_id=RFIFOL(fd,2);
  710. sprintf(tmpsql,"SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, account_id);
  711. if(mysql_query(&mysql_handle, tmpsql)) {
  712. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  713. }
  714. sql_res = mysql_store_result(&mysql_handle) ;
  715. if (sql_res) {
  716. sql_row = mysql_fetch_row(sql_res);
  717. connect_until_time = atol(sql_row[1]);
  718. strcpy(email, sql_row[0]);
  719. }
  720. mysql_free_result(sql_res);
  721. //printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2));
  722. WFIFOW(fd,0) = 0x2717;
  723. WFIFOL(fd,2) = RFIFOL(fd,2);
  724. memcpy(WFIFOP(fd, 6), email, 40);
  725. WFIFOL(fd,46) = (unsigned long) connect_until_time;
  726. WFIFOSET(fd,50);
  727. }
  728. RFIFOSKIP(fd,6);
  729. break;
  730. case 0x2720: // GM
  731. if (RFIFOREST(fd) < 4)
  732. return 0;
  733. if (RFIFOREST(fd) < RFIFOW(fd,2))
  734. return 0;
  735. //oldacc = RFIFOL(fd,4);
  736. printf("change GM isn't support in this login server version.\n");
  737. printf("change GM error 0 %s\n", RFIFOP(fd, 8));
  738. RFIFOSKIP(fd, RFIFOW(fd, 2));
  739. WFIFOW(fd, 0) = 0x2721;
  740. WFIFOL(fd, 2) = RFIFOL(fd,4); // oldacc;
  741. WFIFOL(fd, 6) = 0; // newacc;
  742. WFIFOSET(fd, 10);
  743. return 0;
  744. // Map server send information to change an email of an account via char-server
  745. case 0x2722: // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
  746. if (RFIFOREST(fd) < 86)
  747. return 0;
  748. {
  749. int acc;
  750. char actual_email[40], new_email[40];
  751. acc = RFIFOL(fd,2);
  752. memcpy(actual_email, RFIFOP(fd,6), 40);
  753. memcpy(new_email, RFIFOP(fd,46), 40);
  754. if (e_mail_check(actual_email) == 0)
  755. printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)" RETCODE,
  756. server[id].name, acc, ip);
  757. else if (e_mail_check(new_email) == 0)
  758. printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)" RETCODE,
  759. server[id].name, acc, ip);
  760. else if (strcmpi(new_email, "a@a.com") == 0)
  761. printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)" RETCODE,
  762. server[id].name, acc, ip);
  763. else {
  764. sprintf(tmpsql, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, acc);
  765. if (mysql_query(&mysql_handle, tmpsql))
  766. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  767. sql_res = mysql_store_result(&mysql_handle);
  768. if (sql_res) {
  769. sql_row = mysql_fetch_row(sql_res); //row fetching
  770. if (strcmpi(sql_row[1], actual_email) == 0) {
  771. sprintf(tmpsql, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, new_email, login_db_account_id, acc);
  772. // query
  773. if (mysql_query(&mysql_handle, tmpsql)) {
  774. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  775. }
  776. printf("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s)." RETCODE,
  777. server[id].name, acc, sql_row[0], actual_email, ip);
  778. }
  779. }
  780. }
  781. }
  782. RFIFOSKIP(fd, 86);
  783. break;
  784. case 0x2724: // Receiving of map-server via char-server a status change resquest (by Yor)
  785. if (RFIFOREST(fd) < 10)
  786. return 0;
  787. {
  788. int acc, statut;
  789. acc = RFIFOL(fd,2);
  790. statut = RFIFOL(fd,6);
  791. sprintf(tmpsql, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, acc);
  792. if (mysql_query(&mysql_handle, tmpsql)) {
  793. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  794. }
  795. sql_res = mysql_store_result(&mysql_handle);
  796. if (sql_res) {
  797. sql_row = mysql_fetch_row(sql_res); // row fetching
  798. }
  799. if (atoi(sql_row[0]) != statut && statut != 0) {
  800. unsigned char buf[16];
  801. WBUFW(buf,0) = 0x2731;
  802. WBUFL(buf,2) = acc;
  803. WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
  804. WBUFL(buf,7) = statut; // status or final date of a banishment
  805. charif_sendallwos(-1, buf, 11);
  806. }
  807. sprintf(tmpsql,"UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, statut,login_db_account_id,acc);
  808. //query
  809. if(mysql_query(&mysql_handle, tmpsql)) {
  810. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  811. }
  812. RFIFOSKIP(fd,10);
  813. }
  814. return 0;
  815. case 0x2725: // Receiving of map-server via char-server a ban resquest (by Yor)
  816. if (RFIFOREST(fd) < 18)
  817. return 0;
  818. {
  819. int acc;
  820. struct tm *tmtime;
  821. time_t timestamp, tmptime;
  822. acc = RFIFOL(fd,2);
  823. sprintf(tmpsql, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
  824. if (mysql_query(&mysql_handle, tmpsql)) {
  825. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  826. }
  827. sql_res = mysql_store_result(&mysql_handle);
  828. if (sql_res) {
  829. sql_row = mysql_fetch_row(sql_res); // row fetching
  830. }
  831. tmptime = atol(sql_row[0]);
  832. if (tmptime == 0 || tmptime < time(NULL))
  833. timestamp = time(NULL);
  834. else
  835. timestamp = tmptime;
  836. tmtime = localtime(&timestamp);
  837. tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6);
  838. tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8);
  839. tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10);
  840. tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12);
  841. tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14);
  842. tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16);
  843. timestamp = mktime(tmtime);
  844. if (timestamp != -1) {
  845. if (timestamp <= time(NULL))
  846. timestamp = 0;
  847. if (tmptime != timestamp) {
  848. if (timestamp != 0) {
  849. unsigned char buf[16];
  850. WBUFW(buf,0) = 0x2731;
  851. WBUFL(buf,2) = acc;
  852. WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
  853. WBUFL(buf,7) = timestamp; // status or final date of a banishment
  854. charif_sendallwos(-1, buf, 11);
  855. }
  856. printf("Account: %d Banned until: %ld\n", acc, timestamp);
  857. sprintf(tmpsql, "UPDATE `%s` SET `ban_until` = '%ld', `state`='7' WHERE `%s` = '%d'", login_db, timestamp, login_db_account_id, acc);
  858. // query
  859. if (mysql_query(&mysql_handle, tmpsql)) {
  860. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  861. }
  862. }
  863. }
  864. RFIFOSKIP(fd,18);
  865. break;
  866. }
  867. return 0;
  868. case 0x2727:
  869. if (RFIFOREST(fd) < 6)
  870. return 0;
  871. {
  872. int acc,sex;
  873. unsigned char buf[16];
  874. acc=RFIFOL(fd,4);
  875. sprintf(tmpsql,"SELECT `sex` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
  876. if(mysql_query(&mysql_handle, tmpsql)) {
  877. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  878. return 0;
  879. }
  880. sql_res = mysql_store_result(&mysql_handle) ;
  881. if (sql_res) {
  882. if (mysql_num_rows(sql_res) == 0) {
  883. mysql_free_result(sql_res);
  884. return 0;
  885. }
  886. sql_row = mysql_fetch_row(sql_res); //row fetching
  887. }
  888. if (strcmpi(sql_row[0], "M") == 0)
  889. sex = 1;
  890. else
  891. sex = 0;
  892. sprintf(tmpsql,"UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, (sex==0?'M':'F'), login_db_account_id, acc);
  893. //query
  894. if(mysql_query(&mysql_handle, tmpsql)) {
  895. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  896. }
  897. WBUFW(buf,0) = 0x2723;
  898. WBUFL(buf,2) = acc;
  899. WBUFB(buf,6) = sex;
  900. charif_sendallwos(-1, buf, 7);
  901. RFIFOSKIP(fd,6);
  902. }
  903. return 0;
  904. case 0x2728: // save account_reg
  905. if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  906. return 0;
  907. {
  908. int acc,p,j;
  909. char str[32];
  910. char temp_str[32];
  911. int value;
  912. acc=RFIFOL(fd,4);
  913. if (acc>0){
  914. unsigned char buf[RFIFOW(fd,2)+1];
  915. for(p=8,j=0;p<RFIFOW(fd,2) && j<ACCOUNT_REG2_NUM;p+=36,j++){
  916. memcpy(str,RFIFOP(fd,p),32);
  917. value=RFIFOL(fd,p+32);
  918. sprintf(tmpsql,"DELETE FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d' AND `str`='%s';",acc,jstrescapecpy(temp_str,str));
  919. if(mysql_query(&mysql_handle, tmpsql)) {
  920. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  921. }
  922. sprintf(tmpsql,"INSERT INTO `global_reg_value` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , '%s' , '%d');", acc, jstrescapecpy(temp_str,str), value);
  923. if(mysql_query(&mysql_handle, tmpsql)) {
  924. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  925. }
  926. }
  927. // Send to char
  928. memcpy(WBUFP(buf,0),RFIFOP(fd,0),RFIFOW(fd,2));
  929. WBUFW(buf,0)=0x2729;
  930. charif_sendallwos(fd,buf,WBUFW(buf,2));
  931. }
  932. }
  933. RFIFOSKIP(fd,RFIFOW(fd,2));
  934. //printf("login: save account_reg (from char)\n");
  935. break;
  936. case 0x272a: // Receiving of map-server via char-server a unban resquest (by Yor)
  937. if (RFIFOREST(fd) < 6)
  938. return 0;
  939. {
  940. int acc;
  941. acc = RFIFOL(fd,2);
  942. sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
  943. if(mysql_query(&mysql_handle, tmpsql)) {
  944. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  945. }
  946. sql_res = mysql_store_result(&mysql_handle) ;
  947. if (sql_res) {
  948. sql_row = mysql_fetch_row(sql_res); //row fetching
  949. }
  950. if (atol(sql_row[0]) != 0) {
  951. sprintf(tmpsql,"UPDATE `%s` SET `ban_until` = '0', `state`='0' WHERE `%s` = '%d'", login_db,login_db_account_id,acc);
  952. //query
  953. if(mysql_query(&mysql_handle, tmpsql)) {
  954. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  955. }
  956. break;
  957. }
  958. RFIFOSKIP(fd,6);
  959. }
  960. return 0;
  961. case 0x272b: // Set account_id to online [Wizputer]
  962. if (RFIFOREST(fd) < 6)
  963. return 0;
  964. add_online_user(RFIFOL(fd,2));
  965. RFIFOSKIP(fd,6);
  966. break;
  967. case 0x272c: // Set account_id to offline [Wizputer]
  968. if (RFIFOREST(fd) < 6)
  969. return 0;
  970. remove_online_user(RFIFOL(fd,2));
  971. RFIFOSKIP(fd,6);
  972. break;
  973. default:
  974. printf("login: unknown packet %x! (from char).\n", RFIFOW(fd,0));
  975. session[fd]->eof = 1;
  976. return 0;
  977. }
  978. }
  979. return 0;
  980. }
  981. //Lan ip check added by Kashy
  982. int lan_ip_check(unsigned char *p) {
  983. int y;
  984. int lancheck = 1;
  985. int lancharip[4];
  986. unsigned int k0, k1, k2, k3;
  987. sscanf(lan_char_ip, "%d.%d.%d.%d", &k0, &k1, &k2, &k3);
  988. lancharip[0] = k0; lancharip[1] = k1; lancharip[2] = k2; lancharip[3] = k3;
  989. for(y = 0; y < 4; y++) {
  990. if ((lancharip[y] & subnetmaski[y])!= (p[y]))
  991. lancheck = 0;
  992. break; }
  993. printf("LAN check: %s.\n", (lancheck) ? "\033[1;32mLAN\033[0m" : "\033[1;31mWAN\033[0m");
  994. return lancheck;
  995. }
  996. //----------------------------------------------------------------------------------------
  997. // Default packet parsing (normal players or administation/char-server connection requests)
  998. //----------------------------------------------------------------------------------------
  999. int parse_login(int fd) {
  1000. //int len;
  1001. MYSQL_RES* sql_res ;
  1002. MYSQL_ROW sql_row = NULL;
  1003. char t_uid[100];
  1004. //int sql_fields, sql_cnt;
  1005. struct mmo_account account;
  1006. int result, i;
  1007. unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
  1008. char ip[16];
  1009. sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  1010. if (ipban > 0) {
  1011. //ip ban
  1012. //p[0], p[1], p[2], p[3]
  1013. //request DB connection
  1014. //check
  1015. sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'",
  1016. p[0], p[0], p[1], p[0], p[1], p[2], p[0], p[1], p[2], p[3]);
  1017. if (mysql_query(&mysql_handle, tmpsql)) {
  1018. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1019. }
  1020. sql_res = mysql_store_result(&mysql_handle) ;
  1021. sql_row = mysql_fetch_row(sql_res); //row fetching
  1022. if (atoi(sql_row[0]) >0) {
  1023. // ip ban ok.
  1024. printf ("packet from banned ip : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]);
  1025. sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', 'unknown','-3', 'ip banned')", loginlog_db, p[0], p[1], p[2], p[3]);
  1026. // query
  1027. if(mysql_query(&mysql_handle, tmpsql)) {
  1028. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1029. }
  1030. printf ("close session connection...\n");
  1031. // close connection
  1032. session[fd]->eof = 1;
  1033. } else {
  1034. printf ("packet from ip (ban check ok) : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]);
  1035. }
  1036. mysql_free_result(sql_res);
  1037. }
  1038. if (session[fd]->eof) {
  1039. for(i = 0; i < MAX_SERVERS; i++)
  1040. if (server_fd[i] == fd)
  1041. server_fd[i] = -1;
  1042. close(fd);
  1043. delete_session(fd);
  1044. return 0;
  1045. }
  1046. while(RFIFOREST(fd)>=2){
  1047. printf("parse_login : %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
  1048. switch(RFIFOW(fd,0)){
  1049. case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
  1050. if (RFIFOREST(fd) < 26)
  1051. return 0;
  1052. RFIFOSKIP(fd,26);
  1053. break;
  1054. case 0x204: // New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004)
  1055. if (RFIFOREST(fd) < 18)
  1056. return 0;
  1057. RFIFOSKIP(fd,18);
  1058. break;
  1059. case 0x64: // request client login
  1060. case 0x01dd: // request client login with encrypt
  1061. if(RFIFOREST(fd)< ((RFIFOW(fd, 0) ==0x64)?55:47))
  1062. return 0;
  1063. printf("client connection request %s from %d.%d.%d.%d\n", RFIFOP(fd, 6), p[0], p[1], p[2], p[3]);
  1064. account.version = RFIFOL(fd, 2);
  1065. account.userid = (char*)RFIFOP(fd, 6);
  1066. account.passwd = (char*)RFIFOP(fd, 30);
  1067. #ifdef PASSWORDENC
  1068. account.passwdenc= (RFIFOW(fd,0)==0x64)?0:PASSWORDENC;
  1069. #else
  1070. account.passwdenc=0;
  1071. #endif
  1072. result=mmo_auth(&account, fd);
  1073. jstrescapecpy(t_uid,(char*)RFIFOP(fd, 6));
  1074. if(result==-1){
  1075. int gm_level = isGM(account.account_id);
  1076. if (min_level_to_connect > gm_level) {
  1077. WFIFOW(fd,0) = 0x81;
  1078. WFIFOL(fd,2) = 1; // 01 = Server closed
  1079. WFIFOSET(fd,3);
  1080. } else {
  1081. if (p[0] != 127) {
  1082. sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s','100', 'login ok')", loginlog_db, p[0], p[1], p[2], p[3], t_uid);
  1083. //query
  1084. if(mysql_query(&mysql_handle, tmpsql)) {
  1085. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1086. }
  1087. }
  1088. if (gm_level)
  1089. printf("Connection of the GM (level:%d) account '%s' accepted.\n", gm_level, account.userid);
  1090. else
  1091. printf("Connection of the account '%s' accepted.\n", account.userid);
  1092. server_num=0;
  1093. for(i = 0; i < MAX_SERVERS; i++) {
  1094. if (server_fd[i] >= 0) {
  1095. //Lan check added by Kashy
  1096. if (lan_ip_check(p))
  1097. WFIFOL(fd,47+server_num*32) = inet_addr(lan_char_ip);
  1098. else
  1099. WFIFOL(fd,47+server_num*32) = server[i].ip;
  1100. WFIFOW(fd,47+server_num*32+4) = server[i].port;
  1101. memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20);
  1102. WFIFOW(fd,47+server_num*32+26) = server[i].users;
  1103. WFIFOW(fd,47+server_num*32+28) = server[i].maintenance;
  1104. WFIFOW(fd,47+server_num*32+30) = server[i].new_;
  1105. server_num++;
  1106. }
  1107. }
  1108. // if at least 1 char-server
  1109. if (server_num > 0) {
  1110. WFIFOW(fd,0)=0x69;
  1111. WFIFOW(fd,2)=47+32*server_num;
  1112. WFIFOL(fd,4)=account.login_id1;
  1113. WFIFOL(fd,8)=account.account_id;
  1114. WFIFOL(fd,12)=account.login_id2;
  1115. WFIFOL(fd,16)=0;
  1116. memcpy(WFIFOP(fd,20),account.lastlogin,24);
  1117. WFIFOB(fd,46)=account.sex;
  1118. WFIFOSET(fd,47+32*server_num);
  1119. if(auth_fifo_pos>=AUTH_FIFO_SIZE)
  1120. auth_fifo_pos=0;
  1121. auth_fifo[auth_fifo_pos].account_id=account.account_id;
  1122. auth_fifo[auth_fifo_pos].login_id1=account.login_id1;
  1123. auth_fifo[auth_fifo_pos].login_id2=account.login_id2;
  1124. auth_fifo[auth_fifo_pos].sex=account.sex;
  1125. auth_fifo[auth_fifo_pos].delflag=0;
  1126. auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr;
  1127. auth_fifo_pos++;
  1128. } else {
  1129. WFIFOW(fd,0) = 0x81;
  1130. WFIFOL(fd,2) = 1; // 01 = Server closed
  1131. WFIFOSET(fd,3);
  1132. }
  1133. }
  1134. } else {
  1135. char tmp_sql[512];
  1136. char error[64];
  1137. sprintf(tmp_sql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s', '%d','login failed : %%s')", loginlog_db, p[0], p[1], p[2], p[3], t_uid, result);
  1138. switch((result + 1)) {
  1139. case -2: //-3 = Account Banned
  1140. sprintf(tmpsql,tmp_sql,"Account banned.");
  1141. sprintf(error,"Account banned.");
  1142. break;
  1143. case -1: //-2 = Dynamic Ban
  1144. sprintf(tmpsql,tmp_sql,"dynamic ban (ip and account).");
  1145. sprintf(error,"dynamic ban (ip and account).");
  1146. break;
  1147. case 1: // 0 = Unregistered ID
  1148. sprintf(tmpsql,tmp_sql,"Unregisterd ID.");
  1149. sprintf(error,"Unregisterd ID.");
  1150. break;
  1151. case 2: // 1 = Incorrect Password
  1152. sprintf(tmpsql,tmp_sql,"Incorrect Password.");
  1153. sprintf(error,"Incorrect Password.");
  1154. break;
  1155. case 3: // 2 = This ID is expired
  1156. sprintf(tmpsql,tmp_sql,"Account Expired.");
  1157. sprintf(error,"Account Expired.");
  1158. break;
  1159. case 4: // 3 = Rejected from Server
  1160. sprintf(tmpsql,tmp_sql,"Rejected from server.");
  1161. sprintf(error,"Rejected from server.");
  1162. break;
  1163. case 5: // 4 = You have been blocked by the GM Team
  1164. sprintf(tmpsql,tmp_sql,"Blocked by GM.");
  1165. sprintf(error,"Blocked by GM.");
  1166. break;
  1167. case 6: // 5 = Your Game's EXE file is not the latest version
  1168. sprintf(tmpsql,tmp_sql,"Not latest game EXE.");
  1169. sprintf(error,"Not latest game EXE.");
  1170. break;
  1171. case 7: // 6 = Your are Prohibited to log in until %s
  1172. sprintf(tmpsql,tmp_sql,"Banned.");
  1173. sprintf(error,"Banned.");
  1174. break;
  1175. case 8: // 7 = Server is jammed due to over populated
  1176. sprintf(tmpsql,tmp_sql,"Server Over-population.");
  1177. sprintf(error,"Server Over-population.");
  1178. break;
  1179. case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
  1180. sprintf(tmpsql,tmp_sql," ");
  1181. sprintf(error," ");
  1182. break;
  1183. case 100: // 99 = This ID has been totally erased
  1184. sprintf(tmpsql,tmp_sql,"Account gone.");
  1185. sprintf(error,"Account gone.");
  1186. break;
  1187. default:
  1188. sprintf(tmpsql,tmp_sql,"Uknown Error.");
  1189. sprintf(error,"Uknown Error.");
  1190. break;
  1191. }
  1192. //query
  1193. if(mysql_query(&mysql_handle, tmpsql)) {
  1194. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1195. }
  1196. if ((result == 1) && (dynamic_pass_failure_ban != 0)){ // failed password
  1197. sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%d.%d.%d.%d' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
  1198. loginlog_db, p[0], p[1], p[2], p[3], dynamic_pass_failure_ban_time); //how many times filed account? in one ip.
  1199. if(mysql_query(&mysql_handle, tmpsql)) {
  1200. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1201. }
  1202. //check query result
  1203. sql_res = mysql_store_result(&mysql_handle) ;
  1204. sql_row = mysql_fetch_row(sql_res); //row fetching
  1205. if (atoi(sql_row[0]) >= dynamic_pass_failure_ban_how_many ) {
  1206. sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", p[0], p[1], p[2], dynamic_pass_failure_ban_how_long, t_uid);
  1207. if(mysql_query(&mysql_handle, tmpsql)) {
  1208. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1209. }
  1210. }
  1211. mysql_free_result(sql_res);
  1212. }
  1213. else if (result == -2){ //dynamic banned - add ip to ban list.
  1214. sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", p[0], p[1], p[2], t_uid);
  1215. if(mysql_query(&mysql_handle, tmpsql)) {
  1216. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1217. }
  1218. result = -3;
  1219. }else if(result == 6){ //not lastet version ..
  1220. result = 5;
  1221. }
  1222. sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE %s `%s` = '%s'",login_db, case_sensitive ? "BINARY" : "",login_db_userid, t_uid);
  1223. if(mysql_query(&mysql_handle, tmpsql)) {
  1224. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1225. }
  1226. sql_res = mysql_store_result(&mysql_handle) ;
  1227. if (sql_res) {
  1228. sql_row = mysql_fetch_row(sql_res); //row fetching
  1229. }
  1230. //cannot connect login failed
  1231. memset(WFIFOP(fd,0),'\0',23);
  1232. WFIFOW(fd,0)=0x6a;
  1233. WFIFOB(fd,2)=result;
  1234. if (result == 6) { // 6 = Your are Prohibited to log in until %s
  1235. if (atol(sql_row[0]) != 0) { // if account is banned, we send ban timestamp
  1236. char tmpstr[256];
  1237. time_t ban_until_time;
  1238. ban_until_time = atol(sql_row[0]);
  1239. strftime(tmpstr, 20, date_format, localtime(&ban_until_time));
  1240. tmpstr[19] = '\0';
  1241. memcpy(WFIFOP(fd,3), tmpstr, 20);
  1242. } else { // we send error message
  1243. memcpy(WFIFOP(fd,3), error, 20);
  1244. }
  1245. }
  1246. WFIFOSET(fd,23);
  1247. }
  1248. RFIFOSKIP(fd,(RFIFOW(fd,0)==0x64)?55:47);
  1249. break;
  1250. case 0x01db: // request password key
  1251. if (session[fd]->session_data) {
  1252. printf("login: abnormal request of MD5 key (already opened session).\n");
  1253. session[fd]->eof = 1;
  1254. return 0;
  1255. }
  1256. printf("Request Password key -%s\n",md5key);
  1257. RFIFOSKIP(fd,2);
  1258. WFIFOW(fd,0)=0x01dc;
  1259. WFIFOW(fd,2)=4+md5keylen;
  1260. memcpy(WFIFOP(fd,4),md5key,md5keylen);
  1261. WFIFOSET(fd,WFIFOW(fd,2));
  1262. break;
  1263. case 0x2710: // request Char-server connection
  1264. if(RFIFOREST(fd)<86)
  1265. return 0;
  1266. {
  1267. unsigned char* server_name;
  1268. sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s@%s','100', 'charserver - %s@%d.%d.%d.%d:%d')", loginlog_db, p[0], p[1], p[2], p[3], RFIFOP(fd, 2),RFIFOP(fd, 60),RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58));
  1269. //query
  1270. if(mysql_query(&mysql_handle, tmpsql)) {
  1271. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1272. }
  1273. printf("server connection request %s @ %d.%d.%d.%d:%d (%d.%d.%d.%d)\n",
  1274. RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58),
  1275. p[0], p[1], p[2], p[3]);
  1276. account.userid = (char*)RFIFOP(fd, 2);
  1277. account.passwd = (char*)RFIFOP(fd, 26);
  1278. account.passwdenc = 0;
  1279. server_name = RFIFOP(fd,60);
  1280. result = mmo_auth(&account, fd);
  1281. //printf("Result: %d - Sex: %d - Account ID: %d\n",result,account.sex,(int) account.account_id);
  1282. if(result == -1 && account.sex==2 && account.account_id<MAX_SERVERS && server_fd[account.account_id]==-1){
  1283. printf("Connection of the char-server '%s' accepted.\n", server_name);
  1284. memset(&server[account.account_id], 0, sizeof(struct mmo_char_server));
  1285. server[account.account_id].ip=RFIFOL(fd,54);
  1286. server[account.account_id].port=RFIFOW(fd,58);
  1287. memcpy(server[account.account_id].name,RFIFOP(fd,60),20);
  1288. server[account.account_id].users=0;
  1289. server[account.account_id].maintenance=RFIFOW(fd,82);
  1290. server[account.account_id].new_=RFIFOW(fd,84);
  1291. server_fd[account.account_id]=fd;
  1292. if(anti_freeze_enable)
  1293. server_freezeflag[account.account_id] = 5; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
  1294. sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%ld'", account.account_id);
  1295. //query
  1296. if(mysql_query(&mysql_handle, tmpsql)) {
  1297. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1298. }
  1299. jstrescapecpy(t_uid,server[account.account_id].name);
  1300. sprintf(tmpsql,"INSERT INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%ld', '%s', '%d')",
  1301. account.account_id, server[account.account_id].name,0);
  1302. //query
  1303. if(mysql_query(&mysql_handle, tmpsql)) {
  1304. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1305. }
  1306. WFIFOW(fd,0)=0x2711;
  1307. WFIFOB(fd,2)=0;
  1308. WFIFOSET(fd,3);
  1309. session[fd]->func_parse=parse_fromchar;
  1310. realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK);
  1311. } else {
  1312. WFIFOW(fd, 0) =0x2711;
  1313. WFIFOB(fd, 2)=3;
  1314. WFIFOSET(fd, 3);
  1315. }
  1316. }
  1317. RFIFOSKIP(fd, 86);
  1318. return 0;
  1319. case 0x7530: // request Athena information
  1320. WFIFOW(fd,0)=0x7531;
  1321. WFIFOB(fd,2)=ATHENA_MAJOR_VERSION;
  1322. WFIFOB(fd,3)=ATHENA_MINOR_VERSION;
  1323. WFIFOB(fd,4)=ATHENA_REVISION;
  1324. WFIFOB(fd,5)=ATHENA_RELEASE_FLAG;
  1325. WFIFOB(fd,6)=ATHENA_OFFICIAL_FLAG;
  1326. WFIFOB(fd,7)=ATHENA_SERVER_LOGIN;
  1327. WFIFOW(fd,8)=ATHENA_MOD_VERSION;
  1328. WFIFOSET(fd,10);
  1329. RFIFOSKIP(fd,2);
  1330. printf ("Athena version check...\n");
  1331. break;
  1332. case 0x7532:
  1333. default:
  1334. printf ("End of connection (ip: %s)" RETCODE, ip);
  1335. session[fd]->eof = 1;
  1336. return 0;
  1337. }
  1338. }
  1339. return 0;
  1340. }
  1341. // Console Command Parser [Wizputer]
  1342. int parse_console(char *buf) {
  1343. char *type,*command;
  1344. type = (char *)aMalloc(64);
  1345. command = (char *)aMalloc(64);
  1346. memset(type,0,64);
  1347. memset(command,0,64);
  1348. printf("Console: %s\n",buf);
  1349. if ( sscanf(buf, "%[^:]:%[^\n]", type , command ) < 2 )
  1350. sscanf(buf,"%[^\n]",type);
  1351. printf("Type of command: %s || Command: %s \n",type,command);
  1352. if(buf) aFree(buf);
  1353. if(type) aFree(type);
  1354. if(command) aFree(command);
  1355. return 0;
  1356. }
  1357. //-------------------------------------------------
  1358. // Return numerical value of a switch configuration
  1359. // on/off, english, français, deutsch, español
  1360. //-------------------------------------------------
  1361. int config_switch(const char *str) {
  1362. if (strcmpi(str, "on") == 0 || strcmpi(str, "yes") == 0 || strcmpi(str, "oui") == 0 || strcmpi(str, "ja") == 0 || strcmpi(str, "si") == 0)
  1363. return 1;
  1364. if (strcmpi(str, "off") == 0 || strcmpi(str, "no") == 0 || strcmpi(str, "non") == 0 || strcmpi(str, "nein") == 0)
  1365. return 0;
  1366. return atoi(str);
  1367. }
  1368. //Lan Support conf reading added by Kashy
  1369. int login_lan_config_read(const char *lancfgName){
  1370. int i;
  1371. char subnetmask[128];
  1372. char line[1024], w1[1024], w2[1024];
  1373. FILE *fp;
  1374. fp=fopen(lancfgName, "r");
  1375. if (fp == NULL) {
  1376. printf("file not found: %s\n", lancfgName);
  1377. return 1;
  1378. }
  1379. printf("Start reading of Lan Support configuration file\n");
  1380. while(fgets(line, sizeof(line)-1, fp)){
  1381. if (line[0] == '/' && line[1] == '/')
  1382. continue;
  1383. i = sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  1384. if(i!=2)
  1385. continue;
  1386. else if(strcmpi(w1,"lan_char_ip")==0){
  1387. strcpy(lan_char_ip, w2);
  1388. printf ("set Lan_Char_IP : %s\n",w2);
  1389. }
  1390. else if(strcmpi(w1,"subnetmask")==0){
  1391. unsigned int k0, k1, k2, k3;
  1392. strcpy(subnetmask, w2);
  1393. sscanf(subnetmask, "%d.%d.%d.%d", &k0, &k1, &k2, &k3);
  1394. subnetmaski[0] = k0; subnetmaski[1] = k1; subnetmaski[2] = k2; subnetmaski[3] = k3;
  1395. printf ("set subnetmask : %s\n",w2);
  1396. }
  1397. }
  1398. fclose(fp);
  1399. {
  1400. unsigned int a0, a1, a2, a3;
  1401. unsigned char p[4];
  1402. sscanf(lan_char_ip, "%d.%d.%d.%d", &a0, &a1, &a2, &a3);
  1403. p[0] = a0; p[1] = a1; p[2] = a2; p[3] = a3;
  1404. printf("LAN test of LAN IP of the char-server: ");
  1405. if (lan_ip_check(p) == 0) {
  1406. printf("\033[1;31m***ERROR: LAN IP of the char-server doesn't belong to the specified Sub-network\033[0m\n");
  1407. }
  1408. }
  1409. printf("End reading of Lan Support configuration file\n");
  1410. return 0;
  1411. }
  1412. //-----------------------------------------------------
  1413. //BANNED IP CHECK.
  1414. //-----------------------------------------------------
  1415. int ip_ban_check(int tid, unsigned int tick, int id, int data){
  1416. //query
  1417. if(mysql_query(&mysql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()")) {
  1418. printf("DB server Error - %s\n", mysql_error(&mysql_handle));
  1419. }
  1420. return 0;
  1421. }
  1422. //-----------------------------------------------------
  1423. // reading configuration
  1424. //-----------------------------------------------------
  1425. int login_config_read(const char *cfgName){
  1426. int i;
  1427. char line[1024], w1[1024], w2[1024];
  1428. FILE *fp;
  1429. struct hostent *h = NULL;
  1430. bind_ip_str[0] = '\0';
  1431. fp=fopen(cfgName,"r");
  1432. if(fp==NULL){
  1433. printf("Configuration file (%s) not found.\n", cfgName);
  1434. return 1;
  1435. }
  1436. printf ("start reading configuration...\n");
  1437. while(fgets(line, sizeof(line)-1, fp)){
  1438. if(line[0] == '/' && line[1] == '/')
  1439. continue;
  1440. i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  1441. if(i!=2)
  1442. continue;
  1443. else if (strcmpi(w1, "bind_ip") == 0) {
  1444. //bind_ip_set_ = 1;
  1445. h = gethostbyname (w2);
  1446. if (h != NULL) {
  1447. printf("Login server binding IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  1448. sprintf(bind_ip_str, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  1449. } else
  1450. memcpy(bind_ip_str,w2,16);
  1451. } else if(strcmpi(w1,"login_port")==0){
  1452. login_port=atoi(w2);
  1453. printf ("set login_port : %s\n",w2);
  1454. }
  1455. else if(strcmpi(w1,"ipban")==0){
  1456. ipban=atoi(w2);
  1457. printf ("set ipban : %d\n",ipban);
  1458. }
  1459. //account ban -> ip ban
  1460. else if(strcmpi(w1,"dynamic_account_ban")==0){
  1461. dynamic_account_ban=atoi(w2);
  1462. printf ("set dynamic_account_ban : %d\n",dynamic_account_ban);
  1463. }
  1464. else if(strcmpi(w1,"dynamic_account_ban_class")==0){
  1465. dynamic_account_ban_class=atoi(w2);
  1466. printf ("set dynamic_account_ban_class : %d\n",dynamic_account_ban_class);
  1467. }
  1468. //dynamic password error ban
  1469. else if(strcmpi(w1,"dynamic_pass_failure_ban")==0){
  1470. dynamic_pass_failure_ban=atoi(w2);
  1471. printf ("set dynamic_pass_failure_ban : %d\n",dynamic_pass_failure_ban);
  1472. }
  1473. else if(strcmpi(w1,"dynamic_pass_failure_ban_time")==0){
  1474. dynamic_pass_failure_ban_time=atoi(w2);
  1475. printf ("set dynamic_pass_failure_ban_time : %d\n",dynamic_pass_failure_ban_time);
  1476. }
  1477. else if(strcmpi(w1,"dynamic_pass_failure_ban_how_many")==0){
  1478. dynamic_pass_failure_ban_how_many=atoi(w2);
  1479. printf ("set dynamic_pass_failure_ban_how_many : %d\n",dynamic_pass_failure_ban_how_many);
  1480. }
  1481. else if(strcmpi(w1,"dynamic_pass_failure_ban_how_long")==0){
  1482. dynamic_pass_failure_ban_how_long=atoi(w2);
  1483. printf ("set dynamic_pass_failure_ban_how_long : %d\n",dynamic_pass_failure_ban_how_long);
  1484. }
  1485. else if(strcmpi(w1,"anti_freeze_enable")==0){
  1486. anti_freeze_enable = config_switch(w2);
  1487. }
  1488. else if (strcmpi(w1, "anti_freeze_interval") == 0) {
  1489. ANTI_FREEZE_INTERVAL = atoi(w2);
  1490. if (ANTI_FREEZE_INTERVAL < 5)
  1491. ANTI_FREEZE_INTERVAL = 5; // minimum 5 seconds
  1492. }
  1493. else if (strcmpi(w1, "import") == 0) {
  1494. login_config_read(w2);
  1495. } else if(strcmpi(w1,"imalive_on")==0) { //Added by Mugendai for I'm Alive mod
  1496. imalive_on = atoi(w2); //Added by Mugendai for I'm Alive mod
  1497. } else if(strcmpi(w1,"imalive_time")==0) { //Added by Mugendai for I'm Alive mod
  1498. imalive_time = atoi(w2); //Added by Mugendai for I'm Alive mod
  1499. } else if(strcmpi(w1,"flush_on")==0) { //Added by Mugendai for GUI
  1500. flush_on = atoi(w2); //Added by Mugendai for GUI
  1501. } else if(strcmpi(w1,"flush_time")==0) { //Added by Mugendai for GUI
  1502. flush_time = atoi(w2); //Added by Mugendai for GUI
  1503. } else if(strcmpi(w1, "new_account") == 0){ //Added by Sirius for new account _M/_F
  1504. new_account_flag = atoi(w2); //Added by Sirius for new account _M/_F
  1505. } else if(strcmpi(w1, "check_client_version") == 0){ //Added by Sirius for client version check
  1506. //check_client_version = config_switch(w2); //Added by Sirius for client version check
  1507. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ){
  1508. check_client_version = 1;
  1509. }
  1510. if(strcmpi(w2,"off") == 0 || strcmpi(w2,"no") == 0 ){
  1511. check_client_version = 0;
  1512. }
  1513. } else if(strcmpi(w1, "client_version_to_connect") == 0){ //Added by Sirius for client version check
  1514. client_version_to_connect = atoi(w2); //Added by SIrius for client version check
  1515. } else if(strcmpi(w1,"use_MD5_passwords")==0){
  1516. if (!strcmpi(w2,"yes")) {
  1517. use_md5_passwds=1;
  1518. } else if (!strcmpi(w2,"no")){
  1519. use_md5_passwds=0;
  1520. }
  1521. printf ("Using MD5 Passwords: %s \n",w2);
  1522. }
  1523. else if (strcmpi(w1, "date_format") == 0) { // note: never have more than 19 char for the date!
  1524. switch (atoi(w2)) {
  1525. case 0:
  1526. strcpy(date_format, "%d-%m-%Y %H:%M:%S"); // 31-12-2004 23:59:59
  1527. break;
  1528. case 1:
  1529. strcpy(date_format, "%m-%d-%Y %H:%M:%S"); // 12-31-2004 23:59:59
  1530. break;
  1531. case 2:
  1532. strcpy(date_format, "%Y-%d-%m %H:%M:%S"); // 2004-31-12 23:59:59
  1533. break;
  1534. case 3:
  1535. strcpy(date_format, "%Y-%m-%d %H:%M:%S"); // 2004-12-31 23:59:59
  1536. break;
  1537. }
  1538. }
  1539. else if (strcmpi(w1, "min_level_to_connect") == 0) {
  1540. min_level_to_connect = atoi(w2);
  1541. }
  1542. else if (strcmpi(w1, "check_ip_flag") == 0) {
  1543. check_ip_flag = config_switch(w2);
  1544. }
  1545. else if (strcmpi(w1, "console") == 0) {
  1546. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 )
  1547. console = 1;
  1548. }
  1549. else if (strcmpi(w1, "case_sensitive") == 0) {
  1550. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 )
  1551. case_sensitive = 1;
  1552. if(strcmpi(w2,"off") == 0 || strcmpi(w2,"no") == 0 )
  1553. case_sensitive = 0;
  1554. }
  1555. }
  1556. fclose(fp);
  1557. printf ("End reading configuration...\n");
  1558. return 0;
  1559. }
  1560. void sql_config_read(const char *cfgName){ /* Kalaspuff, to get login_db */
  1561. int i;
  1562. char line[1024], w1[1024], w2[1024];
  1563. FILE *fp=fopen(cfgName,"r");
  1564. if(fp==NULL){
  1565. printf("file not found: %s\n",cfgName);
  1566. exit(1);
  1567. }
  1568. printf("reading configure: %s\n", cfgName);
  1569. while(fgets(line, sizeof(line)-1, fp)){
  1570. if(line[0] == '/' && line[1] == '/')
  1571. continue;
  1572. i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  1573. if(i!=2)
  1574. continue;
  1575. if (strcmpi(w1, "login_db") == 0) {
  1576. strcpy(login_db, w2);
  1577. }
  1578. //add for DB connection
  1579. else if(strcmpi(w1,"login_server_ip")==0){
  1580. strcpy(login_server_ip, w2);
  1581. printf ("set login_server_ip : %s\n",w2);
  1582. }
  1583. else if(strcmpi(w1,"login_server_port")==0){
  1584. login_server_port=atoi(w2);
  1585. printf ("set login_server_port : %s\n",w2);
  1586. }
  1587. else if(strcmpi(w1,"login_server_id")==0){
  1588. strcpy(login_server_id, w2);
  1589. printf ("set login_server_id : %s\n",w2);
  1590. }
  1591. else if(strcmpi(w1,"login_server_pw")==0){
  1592. strcpy(login_server_pw, w2);
  1593. printf ("set login_server_pw : %s\n",w2);
  1594. }
  1595. else if(strcmpi(w1,"login_server_db")==0){
  1596. strcpy(login_server_db, w2);
  1597. printf ("set login_server_db : %s\n",w2);
  1598. }
  1599. //added for custom column names for custom login table
  1600. else if(strcmpi(w1,"login_db_account_id")==0){
  1601. strcpy(login_db_account_id, w2);
  1602. }
  1603. else if(strcmpi(w1,"login_db_userid")==0){
  1604. strcpy(login_db_userid, w2);
  1605. }
  1606. else if(strcmpi(w1,"login_db_user_pass")==0){
  1607. strcpy(login_db_user_pass, w2);
  1608. }
  1609. else if(strcmpi(w1,"login_db_level")==0){
  1610. strcpy(login_db_level, w2);
  1611. }
  1612. //end of custom table config
  1613. else if (strcmpi(w1, "loginlog_db") == 0) {
  1614. strcpy(loginlog_db, w2);
  1615. }
  1616. //support the import command, just like any other config
  1617. else if(strcmpi(w1,"import")==0){
  1618. sql_config_read(w2);
  1619. }
  1620. }
  1621. fclose(fp);
  1622. printf("reading configure done.....\n");
  1623. }
  1624. //-----------------------------------------------------
  1625. //I'm Alive Alert
  1626. //Used to output 'I'm Alive' every few seconds
  1627. //Intended to let frontends know if the app froze
  1628. //-----------------------------------------------------
  1629. int imalive_timer(int tid, unsigned int tick, int id, int data){
  1630. printf("I'm Alive\n");
  1631. return 0;
  1632. }
  1633. //-----------------------------------------------------
  1634. //Flush stdout
  1635. //stdout buffer needs flushed to be seen in GUI
  1636. //-----------------------------------------------------
  1637. int flush_timer(int tid, unsigned int tick, int id, int data){
  1638. fflush(stdout);
  1639. return 0;
  1640. }
  1641. int do_init(int argc,char **argv){
  1642. //initialize login server
  1643. int i;
  1644. //read login configue
  1645. login_config_read( (argc>1)?argv[1]:LOGIN_CONF_NAME );
  1646. sql_config_read(SQL_CONF_NAME);
  1647. login_lan_config_read((argc > 1) ? argv[1] : LAN_CONF_NAME);
  1648. //Generate Passworded Key.
  1649. printf ("memset md5key \n");
  1650. memset(md5key, 0, sizeof(md5key));
  1651. printf ("memset md5key complete\n");
  1652. printf ("memset keyleng\n");
  1653. md5keylen=rand()%4+12;
  1654. for(i=0;i<md5keylen;i++)
  1655. md5key[i]=rand()%255+1;
  1656. printf ("memset keyleng complete\n");
  1657. printf ("set FIFO Size\n");
  1658. for(i=0;i<AUTH_FIFO_SIZE;i++)
  1659. auth_fifo[i].delflag=1;
  1660. printf ("set FIFO Size complete\n");
  1661. printf ("set max servers\n");
  1662. for(i=0;i<MAX_SERVERS;i++)
  1663. server_fd[i]=-1;
  1664. printf ("set max servers complete\n");
  1665. //server port open & binding
  1666. if (bind_ip_str[0] != '\0')
  1667. bind_ip = inet_addr(bind_ip_str);
  1668. else
  1669. bind_ip = INADDR_ANY;
  1670. //login_fd=make_listen_port(login_port);
  1671. login_fd=make_listen_bind(bind_ip,login_port);
  1672. //Auth start
  1673. printf ("Running mmo_auth_sqldb_init()\n");
  1674. mmo_auth_sqldb_init();
  1675. printf ("finished mmo_auth_sqldb_init()\n");
  1676. //sync account when terminating.
  1677. //but no need when you using DBMS (mysql)
  1678. set_termfunc(mmo_db_close);
  1679. //set default parser as parse_login function
  1680. set_defaultparse(parse_login);
  1681. //Added for Mugendais I'm Alive mod
  1682. if(imalive_on)
  1683. add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000);
  1684. //Added by Mugendai for GUI support
  1685. if(flush_on)
  1686. add_timer_interval(gettick()+10, flush_timer,0,0,flush_time);
  1687. if(anti_freeze_enable > 0) {
  1688. add_timer_func_list(char_anti_freeze_system, "char_anti_freeze_system");
  1689. i = add_timer_interval(gettick()+1000, char_anti_freeze_system, 0, 0, ANTI_FREEZE_INTERVAL * 1000);
  1690. }
  1691. // ban deleter timer - 1 minute term
  1692. printf("add interval tic (ip_ban_check)....\n");
  1693. i=add_timer_interval(gettick()+10, ip_ban_check,0,0,60*1000);
  1694. if (console) {
  1695. set_defaultconsoleparse(parse_console);
  1696. start_console();
  1697. }
  1698. // Online user database init
  1699. aFree(online_db);
  1700. online_db = numdb_init();
  1701. printf("The login-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", login_port);
  1702. return 0;
  1703. }