From 0df22ffb8c24d3b89722de875d264ee2c2f7a72e Mon Sep 17 00:00:00 2001 From: ultramage Date: Tue, 27 Nov 2007 19:38:16 +0000 Subject: * TXT/SQL login server code synchronization - exported several core structures to login.h - split off ladmin communication code from the TXT login server - removed all occurences of login_log(); a unified function should be added when SQL's loginlog_db logging code gets synced with TXT - removed conf setting login_log_filename - fixed ladmin getting timeouts since the ping system was changed - removed login/char server_fd[] arrays, added server[].fd instead git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11826 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/char/char.c | 62 +- src/char/int_homun.c | 2 +- src/char_sql/char.c | 56 +- src/ladmin/ladmin.c | 28 +- src/login/Makefile.in | 2 +- src/login/login.c | 2091 ++++++++++--------------------------------------- src/login/login.h | 62 +- src/login_sql/login.c | 250 +++--- src/login_sql/login.h | 43 +- src/map/clif.h | 2 +- src/map/script.c | 2 +- 11 files changed, 696 insertions(+), 1904 deletions(-) (limited to 'src') diff --git a/src/char/char.c b/src/char/char.c index 8f83dbcd2..6a9e94696 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -57,12 +57,12 @@ int save_log = 1; // show loading/saving messages char db_path[1024] = "db"; struct mmo_map_server { + int fd; uint32 ip; uint16 port; int users; unsigned short map[MAX_MAP_PER_SERVER]; } server[MAX_MAP_SERVERS]; -int server_fd[MAX_MAP_SERVERS]; int login_fd, char_fd; char userid[24]; @@ -290,7 +290,7 @@ int search_character_online(int aid, int cid) if(character && character->char_id == cid && character->server > -1) - return server_fd[character->server]; + return server[character->server].fd; return -1; } static void * create_online_char_data(DBKey key, va_list args) @@ -335,7 +335,7 @@ void set_char_online(int map_id, int char_id, int account_id) if (char_id != 99) ShowNotice("set_char_online: Character %d:%d marked in map server %d, but map server %d claims to have (%d:%d) online!\n", character->account_id, character->char_id, character->server, map_id, account_id, char_id); - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); } character->char_id = (char_id==99)?-1:char_id; @@ -402,15 +402,14 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap) static int char_db_kickoffline(DBKey key, void* data, va_list ap) { struct online_char_data* character = (struct online_char_data*)data; - int server = va_arg(ap, int); + int server_id = va_arg(ap, int); - if (server > -1 && character->server != server) + if (server_id > -1 && character->server != server_id) return 0; //Kick out any connected characters, and set them offline as appropiate. if (character->server > -1) - mapif_disconnectplayer(server_fd[character->server], - character->account_id, character->char_id, 1); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1); else if (character->waiting_disconnect == -1) set_char_offline(character->char_id, character->account_id); else return 0; @@ -1375,7 +1374,7 @@ static int create_online_files_sub(DBKey key, void* data, va_list va) } j = character->server; - if (server_fd[j] < 0) { + if (server[j].fd < 0) { server[j].users = 0; return -1; } @@ -1670,7 +1669,7 @@ int count_users(void) users = 0; for(i = 0; i < MAX_MAP_SERVERS; i++) - if (server_fd[i] >= 0) + if (server[i].fd >= 0) users += server[i].users; return users; @@ -1915,7 +1914,7 @@ static void char_auth_ok(int fd, struct char_session_data *sd) { // check if character is not online already. [Skotlex] if (character->server > -1) { //Character already online. KICK KICK KICK - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); if (character->waiting_disconnect == -1) character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); WFIFOW(fd,0) = 0x81; @@ -1991,7 +1990,7 @@ int parse_fromlogin(int fd) send_accounts_tologin(-1, gettick(), 0, 0); // if no map-server already connected, display a message... - ARR_FIND( 0, MAX_MAP_SERVERS, i, server_fd[i] > 0 && server[i].map[0] ); + ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] ); if( i == MAX_MAP_SERVERS ) ShowStatus("Awaiting maps from map-server.\n"); } @@ -2150,9 +2149,7 @@ int parse_fromlogin(int fd) else { // at least 1 map-server - for(i = 0; i < MAX_MAP_SERVERS; i++) - if (server_fd[i] >= 0) - break; + ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd >= 0 ); if (i == MAX_MAP_SERVERS) char_log("'ladmin': Receiving a message for broadcast, but no map-server is online.\n"); else { @@ -2328,7 +2325,7 @@ int parse_fromlogin(int fd) { //Kick out this player. if (character->server > -1) { //Kick it from the map server it is on. - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); if (character->waiting_disconnect == -1) character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0); } else { //Manual kick from char server. @@ -2605,9 +2602,7 @@ int parse_frommap(int fd) int i, j; int id; - for(id = 0; id < MAX_MAP_SERVERS; id++) - if (server_fd[id] == fd) - break; + ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd ); if(id == MAX_MAP_SERVERS) set_eof(fd); if(session[fd]->eof) { @@ -2626,7 +2621,7 @@ int parse_frommap(int fd) WBUFW(buf,2) = j * 4 + 10; mapif_sendallwos(fd, buf, WBUFW(buf,2)); } - server_fd[id] = -1; + server[id].fd = -1; online_char_db->foreach(online_char_db,char_db_setoffline,i); //Tag relevant chars as 'in disconnected' server. } do_close(fd); @@ -2696,7 +2691,7 @@ int parse_frommap(int fd) } // Transmitting the maps of the other map-servers to the new map-server for(x = 0; x < MAX_MAP_SERVERS; x++) { - if (server_fd[x] > 0 && x != id) { + if (server[x].fd > 0 && x != id) { WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER); WFIFOW(fd,0) = 0x2b04; WFIFOL(fd,4) = htonl(server[x].ip); @@ -2768,7 +2763,7 @@ int parse_frommap(int fd) { ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", character->account_id, character->char_id, character->server, id, aid, cid); - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); } character->char_id = cid; character->server = id; @@ -2833,7 +2828,7 @@ int parse_frommap(int fd) name = RFIFOW(fd,18); map_id = search_mapserver(name, ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. if (map_id >= 0) - map_fd = server_fd[map_id]; + map_fd = server[map_id].fd; for(i = 0; i < char_num; i++) { if (char_dat[i].status.account_id == RFIFOL(fd,2) && char_dat[i].status.char_id == RFIFOL(fd,14)) @@ -3180,7 +3175,7 @@ int search_mapserver(unsigned short map, uint32 ip, uint16 port) for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (server_fd[i] > 0 + if (server[i].fd > 0 && (ip == (uint32)-1 || server[i].ip == ip) && (port == (uint16)-1 || server[i].port == port)) { @@ -3355,7 +3350,7 @@ int parse_char(int fd) if (i < 0) { unsigned short j; //First check that there's actually a map server online. - ARR_FIND( 0, MAX_MAP_SERVERS, j, server_fd[j] >= 0 && server[j].map[0] ); + ARR_FIND( 0, MAX_MAP_SERVERS, j, server[j].fd >= 0 && server[j].map[0] ); if (j == MAX_MAP_SERVERS) { ShowInfo("Connection Closed. No map servers available.\n"); WFIFOHEAD(fd,3); @@ -3421,10 +3416,10 @@ int parse_char(int fd) auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; //Send NEW auth packet [Kevin] - if ((map_fd = server_fd[i]) < 1 || session[map_fd] == NULL) + if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL) { ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i); - server_fd[i] = -1; + server[i].fd = -1; memset(&server[i], 0, sizeof(struct mmo_map_server)); //Send server closed. WFIFOHEAD(fd,3); @@ -3626,10 +3621,7 @@ int parse_char(int fd) char* l_pass = RFIFOP(fd,26); l_user[23] = '\0'; l_pass[23] = '\0'; - for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (server_fd[i] <= 0) - break; - } + ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 ); if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) { WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2af9; @@ -3641,7 +3633,7 @@ int parse_char(int fd) WFIFOB(fd,2) = 0; WFIFOSET(fd,3); - server_fd[i] = fd; + server[i].fd = fd; server[i].ip = ntohl(RFIFOL(fd,54)); server[i].port = ntohs(RFIFOW(fd,58)); server[i].users = 0; @@ -3736,7 +3728,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len) c = 0; for(i = 0; i < MAX_MAP_SERVERS; i++) { int fd; - if ((fd = server_fd[i]) > 0) { + if ((fd = server[i].fd) > 0) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -3755,7 +3747,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len) c = 0; for(i = 0; i < MAX_MAP_SERVERS; i++) { int fd; - if ((fd = server_fd[i]) > 0 && fd != sfd) { + if ((fd = server[i].fd) > 0 && fd != sfd) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -3772,7 +3764,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) if (fd >= 0) { for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (fd == server_fd[i]) { + if (fd == server[i].fd) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -4229,7 +4221,7 @@ int do_init(int argc, char **argv) for(i = 0; i < MAX_MAP_SERVERS; i++) { memset(&server[i], 0, sizeof(struct mmo_map_server)); - server_fd[i] = -1; + server[i].fd = -1; } //Read map indexes diff --git a/src/char/int_homun.c b/src/char/int_homun.c index 8a6089a13..be0dcd087 100644 --- a/src/char/int_homun.c +++ b/src/char/int_homun.c @@ -103,7 +103,7 @@ int inter_homun_fromstr(char *str,struct s_homunculus *p) p->hskill[i].id = tmp_int[0]; p->hskill[i].lv = tmp_int[1]; } else - ShowError("Read Homun: Unsupported Skill ID %d for homunculus (Homun ID=%d\n)", tmp_int[0], p->hom_id); + ShowError("Read Homun: Unsupported Skill ID %d for homunculus (Homun ID=%d)\n", tmp_int[0], p->hom_id); next += len; if (str[next] == ' ') next++; diff --git a/src/char_sql/char.c b/src/char_sql/char.c index b44717d65..e18475c36 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -77,12 +77,12 @@ char login_db_level[32] = "level"; int lowest_gm_level = 1; struct mmo_map_server { + int fd; uint32 ip; uint16 port; int users; unsigned short map[MAX_MAP_PER_SERVER]; } server[MAX_MAP_SERVERS]; -int server_fd[MAX_MAP_SERVERS]; int login_fd, char_fd; char userid[24]; @@ -239,7 +239,7 @@ void set_char_online(int map_id, int char_id, int account_id) if (char_id != 99) ShowNotice("set_char_online: Character %d:%d marked in map server %d, but map server %d claims to have (%d:%d) online!\n", character->account_id, character->char_id, character->server, map_id, account_id, char_id); - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); } character->char_id = (char_id==99)?-1:char_id; @@ -329,15 +329,14 @@ static int char_db_setoffline(DBKey key, void* data, va_list ap) static int char_db_kickoffline(DBKey key, void* data, va_list ap) { struct online_char_data* character = (struct online_char_data*)data; - int server = va_arg(ap, int); + int server_id = va_arg(ap, int); - if (server > -1 && character->server != server) + if (server_id > -1 && character->server != server_id) return 0; //Kick out any connected characters, and set them offline as appropiate. if (character->server > -1) - mapif_disconnectplayer(server_fd[character->server], - character->account_id, character->char_id, 1); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1); else if (character->waiting_disconnect == -1) set_char_offline(character->char_id, character->account_id); else return 0; @@ -1423,7 +1422,7 @@ int count_users(void) if (login_fd > 0 && session[login_fd]){ users = 0; for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (server_fd[i] > 0) { + if (server[i].fd > 0) { users += server[i].users; } } @@ -1584,7 +1583,7 @@ static void char_auth_ok(int fd, struct char_session_data *sd) { // check if character is not online already. [Skotlex] if (character->server > -1) { //Character already online. KICK KICK KICK - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); if (character->waiting_disconnect == -1) character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); WFIFOW(fd,0) = 0x81; @@ -1660,7 +1659,7 @@ int parse_fromlogin(int fd) send_accounts_tologin(-1, gettick(), 0, 0); // if no map-server already connected, display a message... - ARR_FIND( 0, MAX_MAP_SERVERS, i, server_fd[i] > 0 && server[i].map[0] ); + ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd > 0 && server[i].map[0] ); if( i == MAX_MAP_SERVERS ) ShowStatus("Awaiting maps from map-server.\n"); } @@ -1892,7 +1891,7 @@ int parse_fromlogin(int fd) { //Kick out this player. if( character->server != -1 ) { //Kick it from the map server it is on. - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); if (character->waiting_disconnect == -1) character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0); } @@ -2124,9 +2123,7 @@ int parse_frommap(int fd) return 0; } - for(id = 0; id < MAX_MAP_SERVERS; id++) - if (server_fd[id] == fd) - break; + ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd ); if(id == MAX_MAP_SERVERS) set_eof(fd); if(session[fd]->eof) { @@ -2146,9 +2143,9 @@ int parse_frommap(int fd) mapif_sendallwos(fd, buf, WBUFW(buf,2)); } memset(&server[id], 0, sizeof(struct mmo_map_server)); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server_fd[id]) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server[id].fd) ) Sql_ShowDebug(sql_handle); - server_fd[id] = -1; + server[id].fd = -1; online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. } do_close(fd); @@ -2215,7 +2212,7 @@ int parse_frommap(int fd) } // Transmitting the maps of the other map-servers to the new map-server for(x = 0; x < MAX_MAP_SERVERS; x++) { - if (server_fd[x] > 0 && x != id) { + if (server[x].fd > 0 && x != id) { WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER); WFIFOW(fd,0) = 0x2b04; WFIFOL(fd,4) = htonl(server[x].ip); @@ -2315,7 +2312,7 @@ int parse_frommap(int fd) { ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", character->account_id, character->char_id, character->server, id, aid, cid); - mapif_disconnectplayer(server_fd[character->server], character->account_id, character->char_id, 2); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); } character->server = id; character->char_id = cid; @@ -2397,7 +2394,7 @@ int parse_frommap(int fd) map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. if (map_id >= 0) - map_fd = server_fd[map_id]; + map_fd = server[map_id].fd; //Char should just had been saved before this packet, so this should be safe. [Skotlex] char_data = uidb_get(char_db_,RFIFOL(fd,14)); if (char_data == NULL) @@ -2754,7 +2751,7 @@ int search_mapserver(unsigned short map, uint32 ip, uint16 port) for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (server_fd[i] > 0 + if (server[i].fd > 0 && (ip == (uint32)-1 || server[i].ip == ip) && (port == (uint16)-1 || server[i].port == port)) { @@ -2930,7 +2927,7 @@ int parse_char(int fd) if (i < 0) { unsigned short j; //First check that there's actually a map server online. - ARR_FIND( 0, MAX_MAP_SERVERS, j, server_fd[j] >= 0 && server[j].map[0] ); + ARR_FIND( 0, MAX_MAP_SERVERS, j, server[j].fd >= 0 && server[j].map[0] ); if (j == MAX_MAP_SERVERS) { ShowInfo("Connection Closed. No map servers available.\n"); WFIFOHEAD(fd,3); @@ -2994,10 +2991,10 @@ int parse_char(int fd) auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; //Send NEW auth packet [Kevin] - if ((map_fd = server_fd[i]) < 1 || session[map_fd] == NULL) + if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL) { ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i); - server_fd[i] = -1; + server[i].fd = -1; memset(&server[i], 0, sizeof(struct mmo_map_server)); //Send server closed. WFIFOHEAD(fd,3); @@ -3174,10 +3171,7 @@ int parse_char(int fd) char* l_pass = RFIFOP(fd,26); l_user[23] = '\0'; l_pass[23] = '\0'; - for(i = 0; i < MAX_MAP_SERVERS; i++) { - if (server_fd[i] <= 0) - break; - } + ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 ); if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) { WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2af9; @@ -3189,7 +3183,7 @@ int parse_char(int fd) WFIFOB(fd,2) = 0; WFIFOSET(fd,3); - server_fd[i] = fd; + server[i].fd = fd; server[i].ip = ntohl(RFIFOL(fd,54)); server[i].port = ntohs(RFIFOW(fd,58)); server[i].users = 0; @@ -3284,7 +3278,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len) c = 0; for(i = 0; i < MAX_MAP_SERVERS; i++) { int fd; - if ((fd = server_fd[i]) > 0) { + if ((fd = server[i].fd) > 0) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -3302,7 +3296,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len) c = 0; for(i = 0; i < MAX_MAP_SERVERS; i++) { int fd; - if ((fd = server_fd[i]) > 0 && fd != sfd) { + if ((fd = server[i].fd) > 0 && fd != sfd) { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -3318,7 +3312,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len) int i; if (fd >= 0) { - ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server_fd[i] ); + ARR_FIND( 0, MAX_MAP_SERVERS, i, fd == server[i].fd ); if( i < MAX_MAP_SERVERS ) { WFIFOHEAD(fd,len); @@ -3835,7 +3829,7 @@ int do_init(int argc, char **argv) for(i = 0; i < MAX_MAP_SERVERS; i++) { memset(&server[i], 0, sizeof(struct mmo_map_server)); - server_fd[i] = -1; + server[i].fd = -1; } //Read map indexes diff --git a/src/ladmin/ladmin.c b/src/ladmin/ladmin.c index 7a7cf3dda..6c50b5ae6 100644 --- a/src/ladmin/ladmin.c +++ b/src/ladmin/ladmin.c @@ -4087,37 +4087,37 @@ int parse_fromlogin(int fd) if (defaultlanguage == 'F') ShowMessage(" Statut: 0 [Compte Ok]\n"); else - ShowMessage(" Statut: 0 [Account OK]\n"); + ShowMessage(" State: 0 [Account OK]\n"); break; case 1: ShowMessage(" Statut: 1 [Unregistered ID]\n"); break; case 2: - ShowMessage(" Statut: 2 [Incorrect Password]\n"); + ShowMessage(" State: 2 [Incorrect Password]\n"); break; case 3: ShowMessage(" Statut: 3 [This ID is expired]\n"); break; case 4: - ShowMessage(" Statut: 4 [Rejected from Server]\n"); + ShowMessage(" State: 4 [Rejected from Server]\n"); break; case 5: ShowMessage(" Statut: 5 [You have been blocked by the GM Team]\n"); break; case 6: - ShowMessage(" Statut: 6 [Your Game's EXE file is not the latest version]\n"); + ShowMessage(" State: 6 [Your Game's EXE file is not the latest version]\n"); break; case 7: ShowMessage(" Statut: 7 [You are Prohibited to log in until %s]\n", error_message); break; case 8: - ShowMessage(" Statut: 8 [Server is jammed due to over populated]\n"); + ShowMessage(" State: 8 [Server is jammed due to over populated]\n"); break; case 9: ShowMessage(" Statut: 9 [No MSG]\n"); break; default: // 100 - ShowMessage(" Statut: %d [This ID is totally erased]\n", (int)RFIFOL(fd,36)); + ShowMessage(" State: %d [This ID is totally erased]\n", (int)RFIFOL(fd,36)); break; } if (defaultlanguage == 'F') { @@ -4232,6 +4232,18 @@ int Connect_login_server(void) return 0; } +// sends a ping packet to login server (will receive pong 0x2718) +int ping_login_server(int tid, unsigned int tick, int id, int data) +{ + if (login_fd > 0 && session[login_fd] != NULL) + { + WFIFOHEAD(login_fd,2); + WFIFOW(login_fd,0) = 0x2719; + WFIFOSET(login_fd,2); + } + return 0; +} + //----------------------------------- // Reading general configuration file //----------------------------------- @@ -4380,6 +4392,10 @@ int do_init(int argc, char **argv) Connect_login_server(); + // keep the char-login connection alive + add_timer_func_list(ping_login_server, "ping_login_server"); + add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000); + // minimalist core doesn't have sockets parsing, // so we have to do this ourselves while (runflag) { diff --git a/src/login/Makefile.in b/src/login/Makefile.in index 187a3eaf0..4bdfb5935 100644 --- a/src/login/Makefile.in +++ b/src/login/Makefile.in @@ -10,7 +10,7 @@ COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/grfio.h ../common/mapindex.h \ ../common/ers.h ../common/md5calc.h -LOGIN_OBJ = obj/login.o +LOGIN_OBJ = obj/login.o obj/admin.o LOGIN_H = login.h @SET_MAKE@ diff --git a/src/login/login.c b/src/login/login.c index 91a2f1996..df80e69ee 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -20,36 +20,10 @@ #include #include // for stat/lstat/fstat -struct Login_Config { - - uint32 login_ip; // the address to bind to - uint16 login_port; // the port to bind to - unsigned int ip_sync_interval; // interval (in minutes) to execute a DNS/IP update (for dynamic IPs) - bool log_login; // whether to log login server actions or not - char date_format[32]; // date format used in messages - bool console; // console input system enabled? - bool new_account_flag; // autoregistration via _M/_F ? -// bool case_sensitive; // are logins case sensitive ? - bool use_md5_passwds; // work with password hashes instead of plaintext passwords? -// bool login_gm_read; // should the login server handle info about gm accounts? - int min_level_to_connect; // minimum level of player/GM (0: player, 1-99: GM) to connect - bool online_check; // reject incoming players that are already registered as online ? - bool check_client_version; // check the clientversion set in the clientinfo ? - int client_version_to_connect; // the client version needed to connect (if checking is enabled) - -// bool ipban; // perform IP blocking (via contents of `ipbanlist`) ? -// bool dynamic_pass_failure_ban; // automatic IP blocking due to failed login attemps ? -// unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures -// unsigned int dynamic_pass_failure_ban_limit; // number of failures needed to trigger the ipban -// unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban - bool use_dnsbl; // dns blacklist blocking ? - char dnsbl_servs[1024]; // comma-separated list of dnsbl servers - -} login_config; +struct Login_Config login_config; int login_fd; // login server socket #define MAX_SERVERS 30 -int server_fd[MAX_SERVERS]; // char server sockets struct mmo_char_server server[MAX_SERVERS]; // char server data // Advanced subnet check [LuzZza] @@ -75,11 +49,10 @@ int account_id_count = START_ACCOUNT_NUM; char account_filename[1024] = "save/account.txt"; char GM_account_filename[1024] = "conf/GM_account.txt"; -char login_log_filename[1024] = "log/login.log"; FILE *log_fp = NULL; char login_log_unknown_packets_filename[1024] = "log/login_unknown_packets.log"; int save_unknown_packets = 0; -long creation_time_GM_account_file; +long creation_time_GM_account_file; // tracks the last-changed timestamp of the gm accounts file int gm_account_filename_check_timer = 15; // Timer to check if GM_account file has been changed and reload GM account automaticaly (in seconds; default: 15) @@ -99,7 +72,6 @@ char *access_deny = NULL; int access_ladmin_allownum = 0; char *access_ladmin_allow = NULL; -int add_to_unlimited_account = 0; // Give possibility or not to adjust (ladmin command: timeadd) the time of an unlimited account. int start_limited_time = -1; // Starting additional sec from now for the limited time at creation of accounts (-1: unlimited time, 0 or more: additional sec from now) struct login_session_data { @@ -107,46 +79,17 @@ struct login_session_data { char md5key[20]; }; -#define AUTH_FIFO_SIZE 256 -struct _auth_fifo { - int account_id; - uint32 login_id1, login_id2; - uint32 ip; - uint8 sex; - bool delflag; -} auth_fifo[AUTH_FIFO_SIZE]; +// auth information of incoming clients +struct _auth_fifo auth_fifo[AUTH_FIFO_SIZE]; int auth_fifo_pos = 0; -struct online_login_data { - int account_id; - int waiting_disconnect; - int char_server; -}; - -// holds info about all existing accounts -struct auth_data { - int account_id; - uint8 sex; // 0, 1, 2 - char userid[24]; - char pass[32+1]; // 23+1 for normal, 32+1 for md5-ed passwords - char lastlogin[24]; - int logincount; - uint32 state; // packet 0x006a value + 1 (0: compte OK) - char email[40]; // e-mail (by default: a@a.com) - char error_message[20]; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a) - time_t ban_until_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban) - time_t connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - char last_ip[16]; // save of last IP of connection - char memo[255]; // a memo field - int account_reg2_num; - struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server) -} *auth_dat = NULL; - +// account database +struct auth_data* auth_dat = NULL; uint32 auth_num = 0, auth_max = 0; // define the number of times that some players must authentify them before to save account file. -// it's just about normal authentification. If an account is created or modified, save is immediatly done. -// An authentification just change last connected IP and date. It already save in log file. +// it's just about normal authentication. If an account is created or modified, save is immediatly done. +// An authentication just change last connected IP and date. It already save in log file. // set minimum auth change before save: #define AUTH_BEFORE_SAVE_FILE 10 // set divider of auth_num to found number of change before save @@ -158,60 +101,34 @@ char admin_pass[24] = ""; char gm_pass[64] = ""; int level_new_gm = 60; +int parse_admin(int fd); -static DBMap* online_db; // int account_id -> struct online_login_data* - -int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len); - -//------------------------------ -// Writing function of logs file -//------------------------------ -int login_log(char *fmt, ...) -{ - if( login_config.log_login ) { - va_list ap; - time_t raw_time; - char tmpstr[2048]; - - if(!log_fp) - log_fp = fopen(login_log_filename, "a"); +//----------------------------------------------------- +// Online User Database [Wizputer] +//----------------------------------------------------- - if (log_fp) { - if (fmt[0] == '\0') // jump a line if no message - fprintf(log_fp, "\n"); - else { - va_start(ap, fmt); - time(&raw_time); - strftime(tmpstr, 24, login_config.date_format, localtime(&raw_time)); - sprintf(tmpstr + strlen(tmpstr), ": %s", fmt); - vfprintf(log_fp, tmpstr, ap); - va_end(ap); - } - fflush(log_fp); // under cygwin or windows, if software is stopped, data are not written in the file -> fflush at every line - } - } +struct online_login_data { + int account_id; + int waiting_disconnect; + int char_server; +}; - return 0; -} +static DBMap* online_db; // int account_id -> struct online_login_data* +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); static void* create_online_user(DBKey key, va_list args) { - struct online_login_data *p; - p = aCalloc(1, sizeof(struct online_login_data)); + struct online_login_data* p; + CREATE(p, struct online_login_data, 1); p->account_id = key.i; p->char_server = -1; p->waiting_disconnect = -1; return p; } -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); - -//----------------------------------------------------- -// Online User Database [Wizputer] -//----------------------------------------------------- void add_online_user(int char_server, int account_id) { - struct online_login_data *p; + struct online_login_data* p; if( !login_config.online_check ) return; p = idb_ensure(online_db, account_id, create_online_user); @@ -246,13 +163,26 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data return 0; } -static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) +//-------------------------------------------------------------------- +// Packet send to all char-servers, except one (wos: without our self) +//-------------------------------------------------------------------- +int charif_sendallwos(int sfd, uint8* buf, size_t len) { - uint8 buf[2]; - ShowInfo("IP Sync in progress...\n"); - WBUFW(buf,0) = 0x2735; - charif_sendallwos(-1, buf, 2); - return 0; + int i, c; + + for( i = 0, c = 0; i < MAX_SERVERS; ++i ) + { + int fd = server[i].fd; + if( session_isValid(fd) && fd != sfd ) + { + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + ++c; + } + } + + return c; } //---------------------------------------------------------------------- @@ -262,10 +192,8 @@ static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) int isGM(int account_id) { unsigned int i; - for(i=0; i < GM_num; i++) - if(gm_account_db[i].account_id == account_id) - return gm_account_db[i].level; - return 0; + ARR_FIND( 0, GM_num, i, gm_account_db[i].account_id == account_id ); + return ( i < GM_num ) ? gm_account_db[i].level : 0; } //---------------------------------------------------------------------- @@ -274,39 +202,33 @@ int isGM(int account_id) void addGM(int account_id, int level) { unsigned int i; - int do_add = 0; - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == account_id) { - do_add = 1; - break; + + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); + if( i < auth_num ) + return; // no such account + + ARR_FIND( 0, GM_num, i, gm_account_db[i].account_id == account_id ); + if( i < GM_num ) + { + if (gm_account_db[i].level == level) + ShowWarning("addGM: GM account %d defined twice (same level: %d).\n", account_id, level); + else { + ShowWarning("addGM: GM account %d defined twice (levels: %d and %d).\n", account_id, gm_account_db[i].level, level); + gm_account_db[i].level = level; } + return; // entry already present } - for(i = 0; i < GM_num; i++) - if (gm_account_db[i].account_id == account_id) { - if (gm_account_db[i].level == level) - ShowWarning("addGM: GM account %d defined twice (same level: %d).\n", account_id, level); - else { - ShowWarning("addGM: GM account %d defined twice (levels: %d and %d).\n", account_id, gm_account_db[i].level, level); - gm_account_db[i].level = level; - } - return; - } - // if new account - if (i == GM_num && do_add) { - if (GM_num >= GM_max) { - GM_max += 256; - gm_account_db = (struct gm_account*)aRealloc(gm_account_db, sizeof(struct gm_account) * GM_max); - memset(gm_account_db + (GM_max - 256), 0, sizeof(struct gm_account) * 256); - } - gm_account_db[GM_num].account_id = account_id; - gm_account_db[GM_num].level = level; - GM_num++; - if (GM_num >= 4000) { - ShowWarning("4000 GM accounts found. Next GM accounts are not read.\n"); - login_log("***WARNING: 4000 GM accounts found. Next GM accounts are not read.\n"); - } + // new account + if (GM_num >= GM_max) { + GM_max += 256; + RECREATE(gm_account_db, struct gm_account, GM_max); } + gm_account_db[GM_num].account_id = account_id; + gm_account_db[GM_num].level = level; + GM_num++; + if (GM_num >= 4000) + ShowWarning("4000 GM accounts found. Next GM accounts are not read.\n"); } //------------------------------------------------------- @@ -322,7 +244,7 @@ int read_gm_account(void) int start_range = 0, end_range = 0, is_range = 0, current_id = 0; if(gm_account_db) aFree(gm_account_db); - gm_account_db = (struct gm_account*)aCalloc(GM_max, sizeof(struct gm_account)); + CREATE(gm_account_db, struct gm_account, 1); GM_num = 0; // get last modify time/date @@ -333,9 +255,6 @@ int read_gm_account(void) if ((fp = fopen(GM_account_filename, "r")) == NULL) { ShowError("read_gm_account: GM accounts file [%s] not found.\n", GM_account_filename); - ShowError(" Actually, there is no GM accounts on the server.\n"); - login_log("read_gm_account: GM accounts file [%s] not found.\n", GM_account_filename); - login_log(" Actually, there is no GM accounts on the server.\n"); return 1; } @@ -373,7 +292,6 @@ int read_gm_account(void) fclose(fp); ShowStatus("read_gm_account: file '%s' read (%d GM accounts found).\n", GM_account_filename, GM_num); - login_log("read_gm_account: file '%s' read (%d GM accounts found).\n", GM_account_filename, GM_num); return 0; } @@ -566,7 +484,7 @@ int mmo_auth_init(void) int server_count = 0; auth_max = 256; - auth_dat = (struct auth_data*)aCalloc(auth_max, sizeof(struct auth_data)); + CREATE(auth_dat, struct auth_data, auth_max); if ((fp = fopen(account_filename, "r")) == NULL) { // no account file -> no account -> no login, including char-server (ERROR) @@ -603,10 +521,7 @@ int mmo_auth_init(void) // Some checks if (account_id > END_ACCOUNT_NUM) { ShowError(CL_RED"mmmo_auth_init: an account has an id higher than %d\n", END_ACCOUNT_NUM); - ShowError(" account id #%d -> account not read (saved in log file)."CL_RESET"\n", account_id); - login_log("mmmo_auth_init: ******Error: an account has an id higher than %d.\n", END_ACCOUNT_NUM); - login_log(" account id #%d -> account not read (saved in next line):\n", account_id); - login_log("%s", line); + ShowError(" account id #%d -> account not read (data is lost!)."CL_RESET"\n", account_id); continue; } userid[23] = '\0'; @@ -614,17 +529,11 @@ int mmo_auth_init(void) for(j = 0; j < auth_num; j++) { if (auth_dat[j].account_id == account_id) { ShowError(CL_RED"mmmo_auth_init: an account has an identical id to another.\n"); - ShowError(" account id #%d -> new account not read (saved in log file)."CL_RED"\n", account_id); - login_log("mmmo_auth_init: ******Error: an account has an identical id to another.\n"); - login_log(" account id #%d -> new account not read (saved in next line):\n", account_id); - login_log("%s", line); + ShowError(" account id #%d -> new account not read (data is lost!)."CL_RED"\n", account_id); break; } else if (strcmp(auth_dat[j].userid, userid) == 0) { ShowError(CL_RED"mmmo_auth_init: account name already exists.\n"); - ShowError(" account name '%s' -> new account not read (saved in log file)."CL_RESET"\n", userid); // 2 lines, account name can be long. - login_log("mmmo_auth_init: ******Error: an account has an identical name to another.\n"); - login_log(" account name '%s' -> new account not read (saved in next line):\n", userid); - login_log("%s", line); + ShowError(" account name '%s' -> new account not read (data is lost!)."CL_RESET"\n", userid); // 2 lines, account name can be long. break; } } @@ -650,7 +559,7 @@ int mmo_auth_init(void) remove_control_chars(lastlogin); strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24); - auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'); + auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm') ? 1 : 0; if (logincount >= 0) auth_dat[auth_num].logincount = logincount; @@ -725,10 +634,7 @@ int mmo_auth_init(void) &account_id, userid, pass, lastlogin, &sex, &logincount, &state, &n)) >= 5) { if (account_id > END_ACCOUNT_NUM) { ShowError(CL_RED"mmmo_auth_init: an account has an id higher than %d\n", END_ACCOUNT_NUM); - ShowError(" account id #%d -> account not read (saved in log file)."CL_RESET"\n", account_id); - login_log("mmmo_auth_init: ******Error: an account has an id higher than %d.\n", END_ACCOUNT_NUM); - login_log(" account id #%d -> account not read (saved in next line):\n", account_id); - login_log("%s", line); + ShowError(" account id #%d -> account not read (data is lost!)."CL_RESET"\n", account_id); continue; } userid[23] = '\0'; @@ -736,17 +642,11 @@ int mmo_auth_init(void) for(j = 0; j < auth_num; j++) { if (auth_dat[j].account_id == account_id) { ShowError(CL_RED"mmo_auth_init: an account has an identical id to another.\n"); - ShowError(" account id #%d -> new account not read (saved in log file)."CL_RESET"\n", account_id); - login_log("mmmo_auth_init: ******Error: an account has an identical id to another.\n"); - login_log(" account id #%d -> new account not read (saved in next line):\n", account_id); - login_log("%s", line); + ShowError(" account id #%d -> new account not read (data is lost!)."CL_RESET"\n", account_id); break; } else if (strcmp(auth_dat[j].userid, userid) == 0) { ShowError(CL_RED"mmo_auth_init: account name already exists.\n"); - ShowError(" account name '%s' -> new account not read (saved in log file)."CL_RESET"\n", userid); - login_log("mmmo_auth_init: ******Error: an account has an identical id to another.\n"); - login_log(" account id #%d -> new account not read (saved in next line):\n", account_id); - login_log("%s", line); + ShowError(" account name '%s' -> new account not read (data is lost!)."CL_RESET"\n", userid); break; } } @@ -755,7 +655,7 @@ int mmo_auth_init(void) if (auth_num >= auth_max) { auth_max += 256; - auth_dat = (struct auth_data*)aRealloc(auth_dat, sizeof(struct auth_data) * auth_max); + RECREATE(auth_dat, struct auth_data, auth_max); } memset(&auth_dat[auth_num], '\0', sizeof(struct auth_data)); @@ -772,7 +672,7 @@ int mmo_auth_init(void) remove_control_chars(lastlogin); strncpy(auth_dat[auth_num].lastlogin, lastlogin, 24); - auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'); + auth_dat[auth_num].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm') ? 1 : 0; if (i >= 6) { if (logincount >= 0) @@ -834,39 +734,29 @@ int mmo_auth_init(void) } fclose(fp); - if (auth_num == 0) { + if( auth_num == 0 ) ShowNotice("mmo_auth_init: No account found in %s.\n", account_filename); - sprintf(line, "No account found in %s.", account_filename); - } else { - if (auth_num == 1) { - ShowStatus("mmo_auth_init: 1 account read in %s,\n", account_filename); - sprintf(line, "1 account read in %s,", account_filename); - } else { - ShowStatus("mmo_auth_init: %d accounts read in %s,\n", auth_num, account_filename); - sprintf(line, "%u accounts read in %s,", auth_num, account_filename); - } - if (GM_count == 0) { - ShowStatus(" of which is no GM account, and "); - sprintf(str, "%s of which is no GM account and", line); - } else if (GM_count == 1) { - ShowStatus(" of which is 1 GM account, and "); - sprintf(str, "%s of which is 1 GM account and", line); - } else { - ShowStatus(" of which is %d GM accounts, and ", GM_count); - sprintf(str, "%s of which is %d GM accounts and", line, GM_count); - } - if (server_count == 0) { - printf("no server account ('S').\n"); - sprintf(line, "%s no server account ('S').", str); - } else if (server_count == 1) { - printf("1 server account ('S').\n"); - sprintf(line, "%s 1 server account ('S').", str); - } else { - printf("%d server accounts ('S').\n", server_count); - sprintf(line, "%s %d server accounts ('S').", str, server_count); - } - } - login_log("%s\n", line); + else + if( auth_num == 1 ) + ShowStatus("mmo_auth_init: 1 account read in %s,\n", account_filename); + else + ShowStatus("mmo_auth_init: %d accounts read in %s,\n", auth_num, account_filename); + + if( GM_count == 0 ) + ShowStatus(" of which is no GM account, and "); + else + if( GM_count == 1 ) + ShowStatus(" of which is 1 GM account, and "); + else + ShowStatus(" of which is %d GM accounts, and ", GM_count); + + if( server_count == 0 ) + ShowStatus(" no server account ('S').\n"); + else + if( server_count == 1 ) + ShowStatus(" 1 server account ('S').\n"); + else + ShowStatus(" %d server accounts ('S').\n", server_count); return 0; } @@ -943,18 +833,18 @@ void mmo_auth_sync(void) //----------------------------------------------------- // Check if we must save accounts file or not // every minute, we check if we must save because we -// have do some authentifications without arrive to -// the minimum of authentifications for the save. +// have do some authentications without arrive to +// the minimum of authentications for the save. // Note: all other modification of accounts (deletion, // change of some informations excepted lastip/ // lastlogintime, creation) are always save // immediatly and set the minimum of -// authentifications to its initialization value. +// authentications to its initialization value. //----------------------------------------------------- int check_auth_sync(int tid, unsigned int tick, int id, int data) { // we only save if necessary: - // we have do some authentifications without do saving + // we have do some authentications without do saving if (auth_before_save_file < AUTH_BEFORE_SAVE_FILE || auth_before_save_file < (int)(auth_num / AUTH_SAVE_FILE_DIVIDER)) mmo_auth_sync(); @@ -962,23 +852,16 @@ int check_auth_sync(int tid, unsigned int tick, int id, int data) return 0; } -//-------------------------------------------------------------------- -// Packet send to all char-servers, except one (wos: without our self) -//-------------------------------------------------------------------- -int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) +//----------------------------------------------------- +// periodic ip address synchronization +//----------------------------------------------------- +static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) { - int i, c, fd; - - for(i = 0, c = 0; i < MAX_SERVERS; i++) { - if ((fd = server_fd[i]) >= 0 && fd != sfd) { - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - c++; - } - } - - return c; + uint8 buf[2]; + ShowInfo("IP Sync in progress...\n"); + WBUFW(buf,0) = 0x2735; + charif_sendallwos(-1, buf, 2); + return 0; } //----------------------------------------------------- @@ -1186,7 +1069,6 @@ int mmo_auth(struct mmo_account* account, int fd) //only continue if amount in this time limit is allowed (account registration flood protection)[Kevin] if(DIFF_TICK(gettick(), new_reg_tick) < 0 && num_regs >= allowed_regs) { ShowNotice("Account registration denied (registration limit exceeded) to %s!\n", ip); - login_log("Notice: Account registration denied (registration limit exceeded) to %s!", ip); return 3; } newaccount = 1; @@ -1201,14 +1083,14 @@ int mmo_auth(struct mmo_account* account, int fd) { if( i != auth_num ) { - login_log("Attempt of creation of an already existant account (account: %s_%c, pass: %s, received pass: %s, ip: %s)\n", account->userid, account->userid[len-1], auth_dat[i].pass, account->passwd, ip); + ShowNotice("Attempt of creation of an already existant account (account: %s_%c, pass: %s, received pass: %s, ip: %s)\n", account->userid, account->userid[len-1], auth_dat[i].pass, account->passwd, ip); return 1; // 1 = Incorrect Password } else { int new_id = mmo_auth_new(account, account->userid[len-1], "a@a.com"); unsigned int tick = gettick(); - login_log("Account creation (account %s (id: %d), pass: %s, sex: %c, connection with _F/_M, ip: %s)\n", account->userid, new_id, account->passwd, account->userid[len-1], ip); + ShowNotice("Account creation (account %s, id: %d, pass: %s, sex: %c, connection with _F/_M, ip: %s)\n", account->userid, new_id, account->passwd, account->userid[len-1], ip); auth_before_save_file = 0; // Creation of an account -> save accounts file immediatly if( DIFF_TICK(tick, new_reg_tick) > 0 ) @@ -1232,7 +1114,7 @@ int mmo_auth(struct mmo_account* account, int fd) if( i == auth_num ) { - login_log("Unknown account (account: %s, received pass: %s, ip: %s)\n", account->userid, account->passwd, ip); + ShowNotice("Unknown account (account: %s, received pass: %s, ip: %s)\n", account->userid, account->passwd, ip); return 0; // 0 = Unregistered ID } @@ -1243,13 +1125,13 @@ int mmo_auth(struct mmo_account* account, int fd) if( !check_password(session[fd]->session_data, account->passwdenc, user_password, auth_dat[i].pass) ) { - login_log("Invalid password (account: %s, pass: %s, received pass: %s, ip: %s)\n", account->userid, auth_dat[i].pass, (account->passwdenc) ? "[MD5]" : account->passwd, ip); + ShowNotice("Invalid password (account: %s, pass: %s, received pass: %s, ip: %s)\n", account->userid, auth_dat[i].pass, (account->passwdenc) ? "[MD5]" : account->passwd, ip); return 1; // 1 = Incorrect Password } if( auth_dat[i].connect_until_time != 0 && auth_dat[i].connect_until_time < time(NULL) ) { - login_log("Connection refused (account: %s, pass: %s, expired ID, ip: %s)\n", account->userid, account->passwd, ip); + ShowNotice("Connection refused (account: %s, pass: %s, expired ID, ip: %s)\n", account->userid, account->passwd, ip); return 2; // 2 = This ID is expired } @@ -1257,13 +1139,13 @@ int mmo_auth(struct mmo_account* account, int fd) { strftime(tmpstr, 20, login_config.date_format, localtime(&auth_dat[i].ban_until_time)); tmpstr[19] = '\0'; - login_log("Connection refused (account: %s, pass: %s, banned until %s, ip: %s)\n", account->userid, account->passwd, tmpstr, ip); + ShowNotice("Connection refused (account: %s, pass: %s, banned until %s, ip: %s)\n", account->userid, account->passwd, tmpstr, ip); return 6; // 6 = Your are Prohibited to log in until %s } if( auth_dat[i].state ) { - login_log("Connection refused (account: %s, pass: %s, state: %d, ip: %s)\n", account->userid, account->passwd, auth_dat[i].state, ip); + ShowNotice("Connection refused (account: %s, pass: %s, state: %d, ip: %s)\n", account->userid, account->passwd, auth_dat[i].state, ip); return auth_dat[i].state - 1; } @@ -1273,8 +1155,8 @@ int mmo_auth(struct mmo_account* account, int fd) if( data && data->char_server > -1 ) { //Request char servers to kick this account out. [Skotlex] - unsigned char buf[8]; - ShowNotice("User [%d] is already online - Rejected.\n",auth_dat[i].account_id); + uint8 buf[8]; + ShowNotice("User '%s' is already online - Rejected.\n", auth_dat[i].userid); WBUFW(buf,0) = 0x2734; WBUFL(buf,2) = auth_dat[i].account_id; charif_sendallwos(-1, buf, 6); @@ -1284,7 +1166,7 @@ int mmo_auth(struct mmo_account* account, int fd) } } - login_log("Authentification accepted (account: %s (id: %d), ip: %s)\n", account->userid, auth_dat[i].account_id, ip); + ShowNotice("Authentication accepted (account: %s, id: %d, ip: %s)\n", account->userid, auth_dat[i].account_id, ip); // auth start : time seed time(&raw_time); @@ -1337,13 +1219,11 @@ int parse_fromchar(int fd) { uint32 i; int j, id; - - uint32 ipl = session[fd]->client_addr; + uint32 ipl; char ip[16]; - ip2str(ipl, ip); - ARR_FIND( 0, MAX_SERVERS, id, server_fd[id] == fd ); - if (id == MAX_SERVERS) + ARR_FIND( 0, MAX_SERVERS, id, server[id].fd == fd ); + if( id == MAX_SERVERS ) {// not a char server set_eof(fd); do_close(fd); @@ -1353,23 +1233,25 @@ int parse_fromchar(int fd) if( session[fd]->eof ) { ShowStatus("Char-server '%s' has disconnected.\n", server[id].name); - login_log("Char-server '%s' has disconnected (ip: %s).\n", server[id].name, ip); - server_fd[id] = -1; + server[id].fd = -1; memset(&server[id], 0, sizeof(struct mmo_char_server)); online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline. do_close(fd); return 0; } + ipl = server[id].ip; + ip2str(ipl, ip); + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); switch( command ) { - + case 0x2709: // request from map-server via char-server to reload GM accounts - login_log("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip); + ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip); read_gm_account(); // send GM accounts to all char-servers send_GM_accounts(-1); @@ -1381,33 +1263,33 @@ int parse_fromchar(int fd) return 0; { int account_id = RFIFOL(fd,2); - for( i = 0; i < AUTH_FIFO_SIZE; ++i ) - { - if( auth_fifo[i].account_id == RFIFOL(fd,2) && - auth_fifo[i].login_id1 == RFIFOL(fd,6) && - auth_fifo[i].login_id2 == RFIFOL(fd,10) && - auth_fifo[i].sex == RFIFOB(fd,14) && - auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) && - !auth_fifo[i].delflag) - { - auth_fifo[i].delflag = 1; - break; - } - } - - if( i != AUTH_FIFO_SIZE && account_id > 0 ) + ARR_FIND( 0, AUTH_FIFO_SIZE, i, + auth_fifo[i].account_id == RFIFOL(fd,2) && + auth_fifo[i].login_id1 == RFIFOL(fd,6) && + auth_fifo[i].login_id2 == RFIFOL(fd,10) && + auth_fifo[i].sex == RFIFOB(fd,14) && + auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) && + !auth_fifo[i].delflag ); + + if( i < AUTH_FIFO_SIZE ) + auth_fifo[i].delflag = 1; + + if( i < AUTH_FIFO_SIZE && account_id > 0 ) {// send ack time_t connect_until_time; char email[40]; unsigned int k; - login_log("Char-server '%s': authentification of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip); + //ShowStatus("Char-server '%s': authentication of the account %d accepted (ip: %s).\n", server[id].name, account_id, ip); ARR_FIND( 0, auth_num, k, auth_dat[k].account_id == account_id ); - if( k != auth_num ) { + if( k < auth_num ) + { strcpy(email, auth_dat[k].email); connect_until_time = auth_dat[k].connect_until_time; - } else { + } + else + { memset(email, 0, sizeof(email)); connect_until_time = 0; } @@ -1421,8 +1303,8 @@ int parse_fromchar(int fd) WFIFOSET(fd,51); } else - {// authentification not found - login_log("Char-server '%s': authentification of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip); + {// authentication not found + ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip); WFIFOHEAD(fd,51); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; @@ -1437,7 +1319,7 @@ int parse_fromchar(int fd) break; case 0x2714: - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; //printf("parse_fromchar: Receiving of the users number of the server '%s': %d\n", server[id].name, RFIFOL(fd,2)); server[id].users = RFIFOL(fd,2); @@ -1453,20 +1335,20 @@ int parse_fromchar(int fd) int acc = RFIFOL(fd,2); safestrncpy(email, (char*)RFIFOP(fd,6), 40); remove_control_chars(email); - if (e_mail_check(email) == 0) - login_log("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n", server[id].name, acc, ip); - else { - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == acc && (strcmp(auth_dat[i].email, "a@a.com") == 0 || auth_dat[i].email[0] == '\0')) { - memcpy(auth_dat[i].email, email, 40); - login_log("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n", server[id].name, acc, email, ip); - // Save - mmo_auth_sync(); - break; - } + if( e_mail_check(email) == 0 ) + ShowNotice("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - e-mail is invalid (account: %d, ip: %s)\n", server[id].name, acc, ip); + else + { + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == acc && (strcmp(auth_dat[i].email, "a@a.com") == 0 || auth_dat[i].email[0] == '\0') ); + if( i == auth_num ) + ShowNotice("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s).\n", server[id].name, acc, ip); + else + { + memcpy(auth_dat[i].email, email, 40); + ShowNotice("Char-server '%s': Create an e-mail on an account with a default e-mail (account: %d, new e-mail: %s, ip: %s).\n", server[id].name, acc, email, ip); + // Save + mmo_auth_sync(); } - if (i == auth_num) - login_log("Char-server '%s': Attempt to create an e-mail on an account with a default e-mail REFUSED - account doesn't exist or e-mail of account isn't default e-mail (account: %d, ip: %s).\n", server[id].name, acc, ip); } RFIFOSKIP(fd,46); @@ -1474,24 +1356,21 @@ int parse_fromchar(int fd) break; case 0x2716: // received an e-mail/limited time request, because a player comes back from a map-server to the char-server - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == (int)RFIFOL(fd,2)) { - login_log("Char-server '%s': e-mail of the account %d found (ip: %s).\n", - server[id].name, RFIFOL(fd,2), ip); - WFIFOW(fd,0) = 0x2717; - WFIFOL(fd,2) = RFIFOL(fd,2); - memcpy(WFIFOP(fd, 6), auth_dat[i].email, 40); - WFIFOL(fd,46) = (unsigned long)auth_dat[i].connect_until_time; - WFIFOSET(fd,50); - break; - } + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == (int)RFIFOL(fd,2) ); + if( i == auth_num ) + ShowNotice("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n", server[id].name, RFIFOL(fd,2), ip); + else + { + //ShowNotice("Char-server '%s': e-mail of the account %d found (ip: %s).\n", server[id].name, RFIFOL(fd,2), ip); + WFIFOW(fd,0) = 0x2717; + WFIFOL(fd,2) = RFIFOL(fd,2); + safestrncpy((char*)WFIFOP(fd, 6), auth_dat[i].email, 40); + WFIFOL(fd,46) = (unsigned long)auth_dat[i].connect_until_time; + WFIFOSET(fd,50); } - if (i == auth_num) - login_log("Char-server '%s': e-mail of the account %d NOT found (ip: %s).\n", - server[id].name, RFIFOL(fd,2), ip); RFIFOSKIP(fd,6); break; @@ -1508,55 +1387,43 @@ int parse_fromchar(int fd) break; case 0x2720: // Request to become a GM - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) return 0; { unsigned char buf[10]; FILE *fp; int acc = RFIFOL(fd,4); - //printf("parse_fromchar: Request to become a GM acount from %d account.\n", acc); WBUFW(buf,0) = 0x2721; WBUFL(buf,2) = acc; WBUFL(buf,6) = 0; - if (strcmp((char*)RFIFOP(fd,8), gm_pass) == 0) { - // only non-GM can become GM - if (isGM(acc) == 0) { - // if we autorise creation - if (level_new_gm > 0) { - // if we can open the file to add the new GM - if ((fp = fopen(GM_account_filename, "a")) != NULL) { - char tmpstr[24]; - time_t raw_time; - time(&raw_time); - strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time)); - fprintf(fp, "\n// %s: @GM command on account %d\n%d %d\n", tmpstr, acc, acc, level_new_gm); - fclose(fp); - WBUFL(buf,6) = level_new_gm; - read_gm_account(); - send_GM_accounts(-1); - ShowNotice("GM Change of the account %d: level 0 -> %d.\n", acc, level_new_gm); - login_log("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s).\n", - server[id].name, acc, level_new_gm, ip); - } else { - ShowError("Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file)\n", acc); - login_log("Char-server '%s': Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n", - server[id].name, acc, ip); - } - } else { - ShowError("Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0))\n", acc); - login_log("Char-server '%s': Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n", - server[id].name, acc, ip); - } - } else { - ShowError("Error of GM change (suggested account: %d (already GM), correct password).\n", acc); - login_log("Char-server '%s': Error of GM change (suggested account: %d (already GM), correct password, ip: %s).\n", - server[id].name, acc, ip); - } - } else { - ShowError("Error of GM change (suggested account: %d, invalid password).\n", acc); - login_log("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s).\n", - server[id].name, acc, ip); + + if( strcmp((char*)RFIFOP(fd,8), gm_pass) != 0 ) // password check + ShowError("Char-server '%s': Error of GM change (suggested account: %d, invalid password, ip: %s).\n", server[id].name, acc, ip); + else + if( isGM(acc) > 0 ) // only non-GM can become GM + ShowError("Char-server '%s': Error of GM change (suggested account: %d (already GM), correct password, ip: %s).\n", server[id].name, acc, ip); + else + if( level_new_gm == 0 ) // if we autorise creation + ShowError("Char-server '%s': Error of GM change (suggested account: %d, correct password, but GM creation is disable (level_new_gm = 0), ip: %s).\n", server[id].name, acc, ip); + else + if( (fp = fopen(GM_account_filename, "a")) == NULL ) // if we can open the file to add the new GM + ShowError("Char-server '%s': Error of GM change (suggested account: %d, correct password, unable to add a GM account in GM accounts file, ip: %s).\n", server[id].name, acc, ip); + else + { + char tmpstr[24]; + time_t raw_time; + time(&raw_time); + strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time)); + fprintf(fp, "\n// %s: @GM command on account %d\n%d %d\n", tmpstr, acc, acc, level_new_gm); + fclose(fp); + WBUFL(buf,6) = level_new_gm; + read_gm_account(); + send_GM_accounts(-1); + + ShowNotice("Char-server '%s': GM Change of the account %d: level 0 -> %d (ip: %s).\n", server[id].name, acc, level_new_gm, ip); + } + // announce gm level update charif_sendallwos(-1, buf, 10); RFIFOSKIP(fd, RFIFOW(fd,2)); @@ -1573,72 +1440,59 @@ int parse_fromchar(int fd) memcpy(actual_email, RFIFOP(fd,6), 40); actual_email[39] = '\0'; remove_control_chars(actual_email); memcpy(new_email, RFIFOP(fd,46), 40); new_email[39] = '\0'; remove_control_chars(new_email); if (e_mail_check(actual_email) == 0) - login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", - server[id].name, acc, ip); + ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", server[id].name, acc, ip); else if (e_mail_check(new_email) == 0) - login_log("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)\n", - server[id].name, acc, ip); + ShowNotice("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)\n", server[id].name, acc, ip); else if (strcmpi(new_email, "a@a.com") == 0) - login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", - server[id].name, acc, ip); + ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", server[id].name, acc, ip); else { - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == acc) { - if (strcmpi(auth_dat[i].email, actual_email) == 0) { - memcpy(auth_dat[i].email, new_email, 40); - login_log("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", - server[id].name, acc, auth_dat[i].userid, new_email, ip); - // Save - mmo_auth_sync(); - } else - login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", - server[id].name, acc, auth_dat[i].userid, auth_dat[i].email, actual_email, ip); - break; - } + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == acc ); + if( i == auth_num ) + ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", server[id].name, acc, ip); + else + if( strcmpi(auth_dat[i].email, actual_email) != 0 ) + ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual e-mail is incorrect (account: %d (%s), actual e-mail: %s, proposed e-mail: %s, ip: %s).\n", server[id].name, acc, auth_dat[i].userid, auth_dat[i].email, actual_email, ip); + else { + memcpy(auth_dat[i].email, new_email, 40); + ShowNotice("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s).\n", server[id].name, acc, auth_dat[i].userid, new_email, ip); + // Save + mmo_auth_sync(); } - if (i == auth_num) - login_log("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but account doesn't exist (account: %d, ip: %s).\n", - server[id].name, acc, ip); } RFIFOSKIP(fd, 86); } break; - case 0x2724: // Receiving of map-server via char-server a status change request + case 0x2724: // Receiving an account state update request from a map-server (relayed via char-server) if (RFIFOREST(fd) < 10) return 0; { - int acc; - uint32 statut; - acc = RFIFOL(fd,2); - statut = RFIFOL(fd,6); - for(i = 0; i < auth_num && auth_dat[i].account_id != acc; i++); + int account_id = RFIFOL(fd,2); + uint32 state = RFIFOL(fd,6); - if (i == auth_num) { - login_log("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n", - server[id].name, acc, statut, ip); - } else { - if (auth_dat[i].state != statut) { - login_log("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n", - server[id].name, acc, statut, ip); - if (statut != 0) { - unsigned char buf[16]; - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = 0; // 0: change of statut, 1: ban - WBUFL(buf,7) = statut; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - for(j = 0; j < AUTH_FIFO_SIZE; j++) - if (auth_fifo[j].account_id == acc) - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) - } - auth_dat[i].state = statut; - // Save - mmo_auth_sync(); - } else - login_log("Char-server '%s': Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n", - server[id].name, acc, statut, ip); + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == account_id ); + if( i == auth_num ) + ShowNotice("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s).\n", server[id].name, account_id, state, ip); + else + if( auth_dat[i].state == state ) + ShowNotice("Char-server '%s': Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s).\n", server[id].name, account_id, state, ip); + else { + ShowNotice("Char-server '%s': Status change (account: %d, new status %d, ip: %s).\n", server[id].name, account_id, state, ip); + if (state != 0) { + unsigned char buf[16]; + WBUFW(buf,0) = 0x2731; + WBUFL(buf,2) = account_id; + WBUFB(buf,6) = 0; // 0: change of state, 1: ban + WBUFL(buf,7) = state; // status or final date of a banishment + charif_sendallwos(-1, buf, 11); + ARR_FIND( 0, AUTH_FIFO_SIZE, j, auth_fifo[j].account_id == account_id ); + if( j < AUTH_FIFO_SIZE ) + auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication) + } + auth_dat[i].state = state; + // Save + mmo_auth_sync(); } RFIFOSKIP(fd,10); @@ -1650,70 +1504,63 @@ int parse_fromchar(int fd) return 0; { int acc = RFIFOL(fd,2); - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == acc) { - time_t timestamp; - struct tm *tmtime; - if (auth_dat[i].ban_until_time == 0 || auth_dat[i].ban_until_time < time(NULL)) - timestamp = time(NULL); + ARR_FIND( 0, auth_num, i, auth_dat[i].account_id == acc ); + if( i == auth_num ) + ShowNotice("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", server[id].name, acc, ip); + else + { + time_t timestamp; + struct tm *tmtime; + if (auth_dat[i].ban_until_time == 0 || auth_dat[i].ban_until_time < time(NULL)) + timestamp = time(NULL); + else + timestamp = auth_dat[i].ban_until_time; + tmtime = localtime(×tamp); + tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6); + tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8); + tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10); + tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12); + tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14); + tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16); + timestamp = mktime(tmtime); + if (timestamp == -1) + ShowNotice("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", server[id].name, acc, ip); + else + { + if (timestamp <= time(NULL)) + timestamp = 0; else - timestamp = auth_dat[i].ban_until_time; - tmtime = localtime(×tamp); - tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6); - tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8); - tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10); - tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12); - tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14); - tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16); - timestamp = mktime(tmtime); - if (timestamp != -1) { - if (timestamp <= time(NULL)) - timestamp = 0; - if (auth_dat[i].ban_until_time != timestamp) { - if (timestamp != 0) { - unsigned char buf[16]; - char tmpstr[2048]; - strftime(tmpstr, 24, login_config.date_format, localtime(×tamp)); - login_log("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", - server[id].name, acc, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip); - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = auth_dat[i].account_id; - WBUFB(buf,6) = 1; // 0: change of statut, 1: ban - WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - for(j = 0; j < AUTH_FIFO_SIZE; j++) - if (auth_fifo[j].account_id == acc) { - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) - break; - } - } else { - login_log("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", - server[id].name, acc, ip); - } - auth_dat[i].ban_until_time = timestamp; - // Save - mmo_auth_sync(); - } else { - login_log("Char-server '%s': Error of ban request (account: %d, no change for ban date, ip: %s).\n", - server[id].name, acc, ip); + { + if (timestamp == 0) + ShowNotice("Char-server '%s': Error of ban request (account: %d, new date unbans the account, ip: %s).\n", server[id].name, acc, ip); + else + { + unsigned char buf[16]; + char tmpstr[2048]; + strftime(tmpstr, 24, login_config.date_format, localtime(×tamp)); + ShowNotice("Char-server '%s': Ban request (account: %d, new final date of banishment: %d (%s), ip: %s).\n", server[id].name, acc, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip); + WBUFW(buf,0) = 0x2731; + WBUFL(buf,2) = auth_dat[i].account_id; + WBUFB(buf,6) = 1; // 0: change of statut, 1: ban + WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment + charif_sendallwos(-1, buf, 11); + ARR_FIND( 0, AUTH_FIFO_SIZE, j, auth_fifo[j].account_id == acc ); + if( j < AUTH_FIFO_SIZE ) + auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication) } - } else { - login_log("Char-server '%s': Error of ban request (account: %d, invalid date, ip: %s).\n", - server[id].name, acc, ip); + auth_dat[i].ban_until_time = timestamp; + // Save + mmo_auth_sync(); } - break; } } - if (i == auth_num) - login_log("Char-server '%s': Error of ban request (account: %d not found, ip: %s).\n", - server[id].name, acc, ip); RFIFOSKIP(fd,18); return 0; } case 0x2727: // Change of sex (sex is reversed) - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; { uint8 sex; @@ -1721,19 +1568,17 @@ int parse_fromchar(int fd) for(i = 0; i < auth_num; i++) { if (auth_dat[i].account_id == acc) { if (auth_dat[i].sex == 2) - login_log("Char-server '%s': Error of sex change - Server account (suggested account: %d, actual sex %d (Server), ip: %s).\n", - server[id].name, acc, auth_dat[i].sex, ip); + ShowNotice("Char-server '%s': Error of sex change - Server account (suggested account: %d, actual sex %d (Server), ip: %s).\n", server[id].name, acc, auth_dat[i].sex, ip); else { unsigned char buf[16]; if (auth_dat[i].sex == 0) sex = 1; else sex = 0; - login_log("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", - server[id].name, acc, (sex == 2) ? 'S' : (sex == 1 ? 'M' : 'F'), ip); + ShowNotice("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s).\n", server[id].name, acc, (sex == 2) ? 'S' : (sex == 1 ? 'M' : 'F'), ip); for(j = 0; j < AUTH_FIFO_SIZE; j++) if (auth_fifo[j].account_id == acc) - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) + auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication) auth_dat[i].sex = sex; WBUFW(buf,0) = 0x2723; WBUFL(buf,2) = acc; @@ -1746,8 +1591,7 @@ int parse_fromchar(int fd) } } if (i == auth_num) - login_log("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n", - server[id].name, acc, ip); + ShowNotice("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s).\n", server[id].name, acc, ip); RFIFOSKIP(fd,6); return 0; @@ -1762,11 +1606,10 @@ int parse_fromchar(int fd) for(i = 0; i < auth_num; i++) { if (auth_dat[i].account_id == acc) { //unsigned char buf[rfifow(fd,2)+1]; - unsigned char *buf; + uint8* buf; int len; - buf = (unsigned char*)aCalloc(RFIFOW(fd,2)+1, sizeof(unsigned char)); - login_log("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", - server[id].name, acc, ip); + CREATE(buf, uint8, RFIFOW(fd,2)+1); + ShowNotice("char-server '%s': receiving (from the char-server) of account_reg2 (account: %d, ip: %s).\n", server[id].name, acc, ip); for(j=0,p=13;jforeach(online_db, online_db_setoffline, id); //Set all chars from this char-server offline first users = RFIFOW(fd,4); for (i = 0; i < users; i++) { @@ -1895,7 +1734,7 @@ int parse_fromchar(int fd) break; case 0x2736: // WAN IP update from char-server - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; server[id].ip = ntohl(RFIFOL(fd,2)); ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip)); @@ -1960,1016 +1799,49 @@ int parse_fromchar(int fd) return 0; } -//--------------------------------------- -// Packet parsing for administation login -//--------------------------------------- -int parse_admin(int fd) +//-------------------------------------------- +// Test to know if an IP come from LAN or WAN. +//-------------------------------------------- +int lan_subnetcheck(uint32 ip) { - unsigned int i, j; - char* account_name; + int i; + ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) ); + return ( i < subnet_count ) ? subnet[i].char_ip : 0; +} +//---------------------------------------------------------------------------------------- +// Default packet parsing (normal players or administation/char-server connection requests) +//---------------------------------------------------------------------------------------- +int parse_login(int fd) +{ + struct mmo_account account; + int result, j; + unsigned int i; uint32 ipl = session[fd]->client_addr; char ip[16]; - ip2str(ipl, ip); if( session[fd]->eof ) { do_close(fd); - ShowInfo("Remote administration has disconnected (session #%d).\n", fd); return 0; } + ip2str(ipl, ip); + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); switch( command ) { - - case 0x7530: // Request of the server version - login_log("'ladmin': Sending of the server version (ip: %s)\n", ip); - WFIFOHEAD(fd,10); - WFIFOW(fd,0) = 0x7531; - WFIFOB(fd,2) = ATHENA_MAJOR_VERSION; - WFIFOB(fd,3) = ATHENA_MINOR_VERSION; - WFIFOB(fd,4) = ATHENA_REVISION; - WFIFOB(fd,5) = ATHENA_RELEASE_FLAG; - WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG; - WFIFOB(fd,7) = ATHENA_SERVER_LOGIN; - WFIFOW(fd,8) = ATHENA_MOD_VERSION; - WFIFOSET(fd,10); - RFIFOSKIP(fd,2); - break; - - case 0x7532: // Request of end of connection - login_log("'ladmin': End of connection (ip: %s)\n", ip); - RFIFOSKIP(fd,2); - set_eof(fd); - break; + case 0x0200: // New alive packet: structure: 0x200 .24B. used to verify if client is always alive. + if (RFIFOREST(fd) < 26) + return 0; + RFIFOSKIP(fd,26); + break; - case 0x7920: // Request of an accounts list - if (RFIFOREST(fd) < 10) - return 0; - { - int st, ed; - uint16 len; - CREATE_BUFFER(id, int, auth_num); - st = RFIFOL(fd,2); - ed = RFIFOL(fd,6); - RFIFOSKIP(fd,10); - WFIFOW(fd,0) = 0x7921; - if (st < 0) - st = 0; - if (ed > END_ACCOUNT_NUM || ed < st || ed <= 0) - ed = END_ACCOUNT_NUM; - login_log("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)\n", st, ed, ip); - // Sort before send - for(i = 0; i < auth_num; i++) { - unsigned int k; - id[i] = i; - for(j = 0; j < i; j++) { - if (auth_dat[id[i]].account_id < auth_dat[id[j]].account_id) { - for(k = i; k > j; k--) { - id[k] = id[k-1]; - } - id[j] = i; // id[i] - break; - } - } - } - // Sending accounts information - len = 4; - for(i = 0; i < auth_num && len < 30000; i++) { - int account_id = auth_dat[id[i]].account_id; // use sorted index - if (account_id >= st && account_id <= ed) { - j = id[i]; - WFIFOL(fd,len) = account_id; - WFIFOB(fd,len+4) = (unsigned char)isGM(account_id); - memcpy(WFIFOP(fd,len+5), auth_dat[j].userid, 24); - WFIFOB(fd,len+29) = auth_dat[j].sex; - WFIFOL(fd,len+30) = auth_dat[j].logincount; - if (auth_dat[j].state == 0 && auth_dat[j].ban_until_time != 0) // if no state and banished - WFIFOL(fd,len+34) = 7; // 6 = Your are Prohibited to log in until %s - else - WFIFOL(fd,len+34) = auth_dat[j].state; - len += 38; - } - } - WFIFOW(fd,2) = len; - WFIFOSET(fd,len); - //if (id) free(id); - DELETE_BUFFER(id); - } - break; - - case 0x7930: // Request for an account creation - if (RFIFOREST(fd) < 91) - return 0; - { - struct mmo_account ma; - memcpy(ma.userid,RFIFOP(fd, 2),NAME_LENGTH); - ma.userid[23] = '\0'; - memcpy(ma.passwd, RFIFOP(fd, 26), NAME_LENGTH); - ma.passwd[23] = '\0'; - memcpy(ma.lastlogin, "-", 2); - ma.sex = RFIFOB(fd,50); - WFIFOW(fd,0) = 0x7931; - WFIFOL(fd,2) = 0xffffffff; - memcpy(WFIFOP(fd,6), RFIFOP(fd,2), 24); - if (strlen(ma.userid) < 4 || strlen(ma.passwd) < 4) { - login_log("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n", - ip); - } else if (ma.sex != 'F' && ma.sex != 'M') { - login_log("'ladmin': Attempt to create an invalid account (account: %s, received pass: %s, invalid sex, ip: %s)\n", - ma.userid, ma.passwd, ip); - } else if (account_id_count > END_ACCOUNT_NUM) { - login_log("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, pass: %s, sex: %c, ip: %s)\n", - ma.userid, ma.passwd, ma.sex, ip); - } else { - remove_control_chars(ma.userid); - remove_control_chars(ma.passwd); - for(i = 0; i < auth_num; i++) { - if (strncmp(auth_dat[i].userid, ma.userid, 24) == 0) { - login_log("'ladmin': Attempt to create an already existing account (account: %s, pass: %s, received pass: %s, ip: %s)\n", - auth_dat[i].userid, auth_dat[i].pass, ma.passwd, ip); - break; - } - } - if (i == auth_num) { - int new_id; - char email[40]; - memcpy(email, RFIFOP(fd,51), 40); - email[39] = '\0'; - remove_control_chars(email); - new_id = mmo_auth_new(&ma, ma.sex, email); - login_log("'ladmin': Account creation (account: %s (id: %d), pass: %s, sex: %c, email: %s, ip: %s)\n", - ma.userid, new_id, ma.passwd, ma.sex, auth_dat[i].email, ip); - WFIFOL(fd,2) = new_id; - mmo_auth_sync(); - } - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,91); - } - break; - - case 0x7932: // Request for an account deletion - if (RFIFOREST(fd) < 26) - return 0; - WFIFOW(fd,0) = 0x7933; - WFIFOL(fd,2) = 0xFFFFFFFF; - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - i = search_account_index(account_name); - if (i != -1) { - // Char-server is notified of deletion (for characters deletion). - unsigned char buf[65535]; - WBUFW(buf,0) = 0x2730; - WBUFL(buf,2) = auth_dat[i].account_id; - charif_sendallwos(-1, buf, 6); - // send answer - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - WFIFOL(fd,2) = auth_dat[i].account_id; - // save deleted account in log file - login_log("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:\n", auth_dat[i].userid, auth_dat[i].account_id, ip); - mmo_auth_tostr((char*)buf, &auth_dat[i]); - login_log("%s\n", buf); - // delete account - memset(auth_dat[i].userid, '\0', sizeof(auth_dat[i].userid)); - auth_dat[i].account_id = -1; - mmo_auth_sync(); - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n", account_name, ip); - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,26); - break; - - case 0x7934: // Request to change a password - if (RFIFOREST(fd) < 50) - return 0; - WFIFOW(fd,0) = 0x7935; - WFIFOL(fd,2) = 0xFFFFFFFF; /// WTF??? an unsigned being set to a -1 - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - i = search_account_index(account_name); - if (i != -1) { - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - memcpy(auth_dat[i].pass, RFIFOP(fd,26), 24); - auth_dat[i].pass[23] = '\0'; - remove_control_chars(auth_dat[i].pass); - WFIFOL(fd,2) = auth_dat[i].account_id; - login_log("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n", - auth_dat[i].userid, auth_dat[i].pass, ip); - mmo_auth_sync(); - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,50); - break; - - case 0x7936: // Request to modify a state - if (RFIFOREST(fd) < 50) - return 0; - { - char error_message[20]; - uint32 statut; - WFIFOW(fd,0) = 0x7937; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - statut = RFIFOL(fd,26); - memcpy(error_message, RFIFOP(fd,30), 20); - error_message[19] = '\0'; - remove_control_chars(error_message); - if (statut != 7 || error_message[0] == '\0') { // 7: // 6 = Your are Prohibited to log in until %s - strcpy(error_message, "-"); - } - i = search_account_index(account_name); - if (i != -1) { - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - WFIFOL(fd,2) = auth_dat[i].account_id; - if (auth_dat[i].state == statut && strcmp(auth_dat[i].error_message, error_message) == 0) - login_log("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)\n", - account_name, statut, ip); - else { - if (statut == 7) - login_log("'ladmin': Modification of a state (account: %s, new state: %d - prohibited to login until '%s', ip: %s)\n", - auth_dat[i].userid, statut, error_message, ip); - else - login_log("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n", - auth_dat[i].userid, statut, ip); - if (auth_dat[i].state == 0) { - unsigned char buf[16]; - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = auth_dat[i].account_id; - WBUFB(buf,6) = 0; // 0: change of statut, 1: ban - WBUFL(buf,7) = statut; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - for(j = 0; j < AUTH_FIFO_SIZE; j++) - if (auth_fifo[j].account_id == auth_dat[i].account_id) - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) - } - auth_dat[i].state = statut; - memcpy(auth_dat[i].error_message, error_message, 20); - mmo_auth_sync(); - } - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n", - account_name, statut, ip); - } - WFIFOL(fd,30) = statut; - } - WFIFOSET(fd,34); - RFIFOSKIP(fd,50); - break; - - case 0x7938: // Request for servers list and # of online players - { - uint8 server_num = 0; - login_log("'ladmin': Sending of servers list (ip: %s)\n", ip); - for(i = 0; i < MAX_SERVERS; i++) { - if (server_fd[i] >= 0) { - WFIFOL(fd,4+server_num*32) = htonl(server[i].ip); - WFIFOW(fd,4+server_num*32+4) = htons(server[i].port); - memcpy(WFIFOP(fd,4+server_num*32+6), server[i].name, 20); - WFIFOW(fd,4+server_num*32+26) = server[i].users; - WFIFOW(fd,4+server_num*32+28) = server[i].maintenance; - WFIFOW(fd,4+server_num*32+30) = server[i].new_; - server_num++; - } - } - WFIFOW(fd,0) = 0x7939; - WFIFOW(fd,2) = 4 + 32 * server_num; - WFIFOSET(fd,4+32*server_num); - RFIFOSKIP(fd,2); - break; - } - - case 0x793a: // Request to password check - if (RFIFOREST(fd) < 50) - return 0; - WFIFOW(fd,0) = 0x793b; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - i = search_account_index(account_name); - if (i != -1) { - char pass[25]; - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - memcpy(pass, RFIFOP(fd,26), 24); - pass[24] = '\0'; - remove_control_chars(pass); - if (strcmp(auth_dat[i].pass, pass) == 0) { - WFIFOL(fd,2) = auth_dat[i].account_id; - login_log("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n", - auth_dat[i].userid, auth_dat[i].pass, ip); - } else { - login_log("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n", - auth_dat[i].userid, pass, ip); - } - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,50); - break; - - case 0x793c: // Request to modify sex - if (RFIFOREST(fd) < 27) - return 0; - WFIFOW(fd,0) = 0x793d; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - memcpy(WFIFOP(fd,6), account_name, 24); - { - char sex; - sex = RFIFOB(fd,26); - if (sex != 'F' && sex != 'M') { - if (sex > 31) - login_log("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n", - account_name, sex, ip); - else - login_log("'ladmin': Attempt to give an invalid sex (account: %s, received sex: 'control char', ip: %s)\n", - account_name, ip); - } else { - i = search_account_index(account_name); - if (i != -1) { - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - if (auth_dat[i].sex != ((sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'))) { - unsigned char buf[16]; - WFIFOL(fd,2) = auth_dat[i].account_id; - for(j = 0; j < AUTH_FIFO_SIZE; j++) - if (auth_fifo[j].account_id == auth_dat[i].account_id) - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) - auth_dat[i].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'); - login_log("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n", - auth_dat[i].userid, sex, ip); - mmo_auth_sync(); - // send to all char-server the change - WBUFW(buf,0) = 0x2723; - WBUFL(buf,2) = auth_dat[i].account_id; - WBUFB(buf,6) = auth_dat[i].sex; - charif_sendallwos(-1, buf, 7); - } else { - login_log("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n", - auth_dat[i].userid, sex, ip); - } - } else { - login_log("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n", - account_name, sex, ip); - } - } - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,27); - break; - - case 0x793e: // Request to modify GM level - if (RFIFOREST(fd) < 27) - return 0; - WFIFOW(fd,0) = 0x793f; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - memcpy(WFIFOP(fd,6), account_name, 24); - { - char new_gm_level; - new_gm_level = RFIFOB(fd,26); - if (new_gm_level < 0 || new_gm_level > 99) { - login_log("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n", - account_name, (int)new_gm_level, ip); - } else { - i = search_account_index(account_name); - if (i != -1) { - int acc = auth_dat[i].account_id; - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - if (isGM(acc) != new_gm_level) { - // modification of the file - FILE *fp, *fp2; - int lock; - char line[512]; - int GM_account, GM_level; - int modify_flag; - char tmpstr[24]; - time_t raw_time; - if ((fp2 = lock_fopen(GM_account_filename, &lock)) != NULL) { - if ((fp = fopen(GM_account_filename, "r")) != NULL) { - time(&raw_time); - strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time)); - modify_flag = 0; - // read/write GM file - while(fgets(line, sizeof(line), fp)) - { - while(line[0] != '\0' && (line[strlen(line)-1] == '\n' || line[strlen(line)-1] == '\r')) - line[strlen(line)-1] = '\0'; // TODO: remove this - if ((line[0] == '/' && line[1] == '/') || line[0] == '\0') - fprintf(fp2, "%s\n", line); - else { - if (sscanf(line, "%d %d", &GM_account, &GM_level) != 2 && sscanf(line, "%d: %d", &GM_account, &GM_level) != 2) - fprintf(fp2, "%s\n", line); - else if (GM_account != acc) - fprintf(fp2, "%s\n", line); - else if (new_gm_level < 1) { - fprintf(fp2, "// %s: 'ladmin' GM level removed on account %d '%s' (previous level: %d)\n//%d %d\n", tmpstr, acc, auth_dat[i].userid, GM_level, acc, new_gm_level); - modify_flag = 1; - } else { - fprintf(fp2, "// %s: 'ladmin' GM level on account %d '%s' (previous level: %d)\n%d %d\n", tmpstr, acc, auth_dat[i].userid, GM_level, acc, new_gm_level); - modify_flag = 1; - } - } - } - if (modify_flag == 0) - fprintf(fp2, "// %s: 'ladmin' GM level on account %d '%s' (previous level: 0)\n%d %d\n", tmpstr, acc, auth_dat[i].userid, acc, new_gm_level); - fclose(fp); - } else { - login_log("'ladmin': Attempt to modify of a GM level - impossible to read GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", - auth_dat[i].userid, acc, (int)new_gm_level, ip); - } - if (lock_fclose(fp2, GM_account_filename, &lock) == 0) { - WFIFOL(fd,2) = acc; - login_log("'ladmin': Modification of a GM level (account: %s (%d), new GM level: %d, ip: %s)\n", - auth_dat[i].userid, acc, (int)new_gm_level, ip); - // read and send new GM informations - read_gm_account(); - send_GM_accounts(-1); - } else { - login_log("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", - auth_dat[i].userid, acc, (int)new_gm_level, ip); - } - } else { - login_log("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", - auth_dat[i].userid, acc, (int)new_gm_level, ip); - } - } else { - login_log("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n", - auth_dat[i].userid, acc, (int)new_gm_level, ip); - } - } else { - login_log("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n", - account_name, (int)new_gm_level, ip); - } - } - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,27); - break; - - case 0x7940: // Request to modify e-mail - if (RFIFOREST(fd) < 66) - return 0; - WFIFOW(fd,0) = 0x7941; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - memcpy(WFIFOP(fd,6), account_name, 24); - { - char email[40]; - memcpy(email, RFIFOP(fd,26), 40); - if (e_mail_check(email) == 0) { - login_log("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n", - account_name, ip); - } else { - remove_control_chars(email); - i = search_account_index(account_name); - if (i != -1) { - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - memcpy(auth_dat[i].email, email, 40); - WFIFOL(fd,2) = auth_dat[i].account_id; - login_log("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n", - auth_dat[i].userid, email, ip); - mmo_auth_sync(); - } else { - login_log("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)\n", - account_name, email, ip); - } - } - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,66); - break; - - case 0x7942: // Request to modify memo field - if ((int)RFIFOREST(fd) < 28 || (int)RFIFOREST(fd) < (28 + RFIFOW(fd,26))) - return 0; - WFIFOW(fd,0) = 0x7943; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - i = search_account_index(account_name); - if (i != -1) { - int size_of_memo = sizeof(auth_dat[i].memo); - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - memset(auth_dat[i].memo, '\0', size_of_memo); - if (RFIFOW(fd,26) == 0) { - strncpy(auth_dat[i].memo, "-", size_of_memo); - } else if (RFIFOW(fd,26) > size_of_memo - 1) { - memcpy(auth_dat[i].memo, RFIFOP(fd,28), size_of_memo - 1); - } else { - memcpy(auth_dat[i].memo, RFIFOP(fd,28), RFIFOW(fd,26)); - } - auth_dat[i].memo[size_of_memo - 1] = '\0'; - remove_control_chars(auth_dat[i].memo); - WFIFOL(fd,2) = auth_dat[i].account_id; - login_log("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n", - auth_dat[i].userid, auth_dat[i].memo, ip); - mmo_auth_sync(); - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,28 + RFIFOW(fd,26)); - break; - - case 0x7944: // Request to found an account id - if (RFIFOREST(fd) < 26) - return 0; - WFIFOW(fd,0) = 0x7945; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - i = search_account_index(account_name); - if (i != -1) { - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - WFIFOL(fd,2) = auth_dat[i].account_id; - login_log("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)\n", - auth_dat[i].userid, auth_dat[i].account_id, ip); - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,26); - break; - - case 0x7946: // Request to found an account name - if (RFIFOREST(fd) < 6) - return 0; - WFIFOW(fd,0) = 0x7947; - WFIFOL(fd,2) = RFIFOL(fd,2); - memset(WFIFOP(fd,6), '\0', 24); - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == (int)RFIFOL(fd,2)) { - strncpy((char*)WFIFOP(fd,6), auth_dat[i].userid, 24); - login_log("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n", - auth_dat[i].userid, RFIFOL(fd,2), ip); - break; - } - } - if (i == auth_num) { - login_log("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n", - RFIFOL(fd,2), ip); - strncpy((char*)WFIFOP(fd,6), "", 24); - } - WFIFOSET(fd,30); - RFIFOSKIP(fd,6); - break; - - case 0x7948: // Request to change the validity limit (timestamp) (absolute value) - if (RFIFOREST(fd) < 30) - return 0; - { - time_t timestamp; - char tmpstr[2048]; - WFIFOW(fd,0) = 0x7949; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - timestamp = (time_t)RFIFOL(fd,26); - strftime(tmpstr, 24, login_config.date_format, localtime(×tamp)); - i = search_account_index(account_name); - if (i != -1) { - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - login_log("'ladmin': Change of a validity limit (account: %s, new validity: %d (%s), ip: %s)\n", - auth_dat[i].userid, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip); - auth_dat[i].connect_until_time = timestamp; - WFIFOL(fd,2) = auth_dat[i].account_id; - mmo_auth_sync(); - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %d (%s), ip: %s)\n", - account_name, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip); - } - WFIFOL(fd,30) = (unsigned int)timestamp; - } - WFIFOSET(fd,34); - RFIFOSKIP(fd,30); - break; - - case 0x794a: // Request to change the final date of a banishment (timestamp) (absolute value) - if (RFIFOREST(fd) < 30) - return 0; - { - time_t timestamp; - char tmpstr[2048]; - WFIFOW(fd,0) = 0x794b; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - timestamp = (time_t)RFIFOL(fd,26); - if (timestamp <= time(NULL)) - timestamp = 0; - strftime(tmpstr, 24, login_config.date_format, localtime(×tamp)); - i = search_account_index(account_name); - if (i != -1) { - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - WFIFOL(fd,2) = auth_dat[i].account_id; - login_log("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %d (%s), ip: %s)\n", - auth_dat[i].userid, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip); - if (auth_dat[i].ban_until_time != timestamp) { - if (timestamp != 0) { - unsigned char buf[16]; - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = auth_dat[i].account_id; - WBUFB(buf,6) = 1; // 0: change of statut, 1: ban - WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - for(j = 0; j < AUTH_FIFO_SIZE; j++) - if (auth_fifo[j].account_id == auth_dat[i].account_id) - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) - } - auth_dat[i].ban_until_time = timestamp; - mmo_auth_sync(); - } - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %d (%s), ip: %s)\n", - account_name, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip); - } - WFIFOL(fd,30) = (unsigned int)timestamp; - } - WFIFOSET(fd,34); - RFIFOSKIP(fd,30); - break; - - case 0x794c: // Request to change the final date of a banishment (timestamp) (relative change) - if (RFIFOREST(fd) < 38) - return 0; - { - time_t timestamp; - struct tm *tmtime; - char tmpstr[2048]; - WFIFOW(fd,0) = 0x794d; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - i = search_account_index(account_name); - if (i != -1) { - WFIFOL(fd,2) = auth_dat[i].account_id; - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - if (auth_dat[i].ban_until_time == 0 || auth_dat[i].ban_until_time < time(NULL)) - timestamp = time(NULL); - else - timestamp = auth_dat[i].ban_until_time; - tmtime = localtime(×tamp); - tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26); - tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28); - tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30); - tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32); - tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34); - tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36); - timestamp = mktime(tmtime); - if (timestamp != -1) { - if (timestamp <= time(NULL)) - timestamp = 0; - strftime(tmpstr, 24, login_config.date_format, localtime(×tamp)); - login_log("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", - auth_dat[i].userid, (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip); - if (auth_dat[i].ban_until_time != timestamp) { - if (timestamp != 0) { - unsigned char buf[16]; - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = auth_dat[i].account_id; - WBUFB(buf,6) = 1; // 0: change of statut, 1: ban - WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment - charif_sendallwos(-1, buf, 11); - for(j = 0; j < AUTH_FIFO_SIZE; j++) - if (auth_fifo[j].account_id == auth_dat[i].account_id) { - auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification) - break; - } - } - auth_dat[i].ban_until_time = timestamp; - mmo_auth_sync(); - } - } else { - strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].ban_until_time)); - login_log("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", - auth_dat[i].userid, auth_dat[i].ban_until_time, (auth_dat[i].ban_until_time == 0 ? "no banishment" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip); - } - WFIFOL(fd,30) = (unsigned long)auth_dat[i].ban_until_time; - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - WFIFOL(fd,30) = 0; - } - } - WFIFOSET(fd,34); - RFIFOSKIP(fd,38); - break; - - case 0x794e: // Request to send a broadcast message - if (RFIFOREST(fd) < 8 || RFIFOREST(fd) < (8 + RFIFOL(fd,4))) - return 0; - WFIFOW(fd,0) = 0x794f; - WFIFOW(fd,2) = 0xFFFF; // WTF??? - if (RFIFOL(fd,4) < 1) { - login_log("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)\n", - ip); - } else { - // at least 1 char-server - for(i = 0; i < MAX_SERVERS; i++) - if (server_fd[i] >= 0) - break; - if (i == MAX_SERVERS) { - login_log("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)\n", - ip); - } else { - unsigned char buf[32000]; - char message[32000]; - WFIFOW(fd,2) = 0; - memset(message, '\0', sizeof(message)); - memcpy(message, RFIFOP(fd,8), RFIFOL(fd,4)); - message[sizeof(message)-1] = '\0'; - remove_control_chars(message); - if (RFIFOW(fd,2) == 0) - login_log("'ladmin': Receiving a message for broadcast (message (in yellow): %s, ip: %s)\n", - message, ip); - else - login_log("'ladmin': Receiving a message for broadcast (message (in blue): %s, ip: %s)\n", - message, ip); - // send same message to all char-servers (no answer) - memcpy(WBUFP(buf,0), RFIFOP(fd,0), 8 + RFIFOL(fd,4)); - WBUFW(buf,0) = 0x2726; - charif_sendallwos(-1, buf, 8 + RFIFOL(fd,4)); - } - } - WFIFOSET(fd,4); - RFIFOSKIP(fd,8 + RFIFOL(fd,4)); - break; - - case 0x7950: // Request to change the validity limite (timestamp) (relative change) - if (RFIFOREST(fd) < 38) - return 0; - { - time_t timestamp; - struct tm *tmtime; - char tmpstr[2048]; - char tmpstr2[2048]; - WFIFOW(fd,0) = 0x7951; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - i = search_account_index(account_name); - if (i != -1) { - WFIFOL(fd,2) = auth_dat[i].account_id; - memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24); - timestamp = auth_dat[i].connect_until_time; - if (add_to_unlimited_account == 0 && timestamp == 0) { - login_log("'ladmin': Attempt to adjust the validity limit of an unlimited account (account: %s, ip: %s)\n", - auth_dat[i].userid, ip); - WFIFOL(fd,30) = 0; - } else { - if (timestamp == 0 || timestamp < time(NULL)) - timestamp = time(NULL); - tmtime = localtime(×tamp); - tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26); - tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28); - tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30); - tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32); - tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34); - tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36); - timestamp = mktime(tmtime); - if (timestamp != -1) { - strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].connect_until_time)); - strftime(tmpstr2, 24, login_config.date_format, localtime(×tamp)); - login_log("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", - auth_dat[i].userid, auth_dat[i].connect_until_time, (auth_dat[i].connect_until_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "unlimited" : tmpstr2), ip); - auth_dat[i].connect_until_time = timestamp; - mmo_auth_sync(); - WFIFOL(fd,30) = (unsigned long)auth_dat[i].connect_until_time; - } else { - strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].connect_until_time)); - login_log("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", - auth_dat[i].userid, auth_dat[i].connect_until_time, (auth_dat[i].connect_until_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip); - WFIFOL(fd,30) = 0; - } - } - } else { - memcpy(WFIFOP(fd,6), account_name, 24); - login_log("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - WFIFOL(fd,30) = 0; - } - } - WFIFOSET(fd,34); - RFIFOSKIP(fd,38); - break; - - case 0x7952: // Request about informations of an account (by account name) - if (RFIFOREST(fd) < 26) - return 0; - WFIFOW(fd,0) = 0x7953; - WFIFOL(fd,2) = 0xFFFFFFFF; // WTF??? - account_name = (char*)RFIFOP(fd,2); - account_name[23] = '\0'; - remove_control_chars(account_name); - i = search_account_index(account_name); - if (i != -1) { - WFIFOL(fd,2) = auth_dat[i].account_id; - WFIFOB(fd,6) = (unsigned char)isGM(auth_dat[i].account_id); - memcpy(WFIFOP(fd,7), auth_dat[i].userid, 24); - WFIFOB(fd,31) = auth_dat[i].sex; - WFIFOL(fd,32) = auth_dat[i].logincount; - WFIFOL(fd,36) = auth_dat[i].state; - memcpy(WFIFOP(fd,40), auth_dat[i].error_message, 20); - memcpy(WFIFOP(fd,60), auth_dat[i].lastlogin, 24); - memcpy(WFIFOP(fd,84), auth_dat[i].last_ip, 16); - memcpy(WFIFOP(fd,100), auth_dat[i].email, 40); - WFIFOL(fd,140) = (unsigned long)auth_dat[i].connect_until_time; - WFIFOL(fd,144) = (unsigned long)auth_dat[i].ban_until_time; - WFIFOW(fd,148) = (uint16)strlen(auth_dat[i].memo); - if (auth_dat[i].memo[0]) { - memcpy(WFIFOP(fd,150), auth_dat[i].memo, strlen(auth_dat[i].memo)); - } - login_log("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n", - auth_dat[i].userid, auth_dat[i].account_id, ip); - WFIFOSET(fd,150+strlen(auth_dat[i].memo)); - } else { - memcpy(WFIFOP(fd,7), account_name, 24); - WFIFOW(fd,148) = 0; - login_log("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n", - account_name, ip); - WFIFOSET(fd,150); - } - RFIFOSKIP(fd,26); - break; - - case 0x7954: // Request about information of an account (by account id) - if (RFIFOREST(fd) < 6) - return 0; - WFIFOW(fd,0) = 0x7953; - WFIFOL(fd,2) = RFIFOL(fd,2); - memset(WFIFOP(fd,7), '\0', 24); - for(i = 0; i < auth_num; i++) { - if (auth_dat[i].account_id == (int)RFIFOL(fd,2)) { - login_log("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n", - auth_dat[i].userid, RFIFOL(fd,2), ip); - WFIFOB(fd,6) = (unsigned char)isGM(auth_dat[i].account_id); - memcpy(WFIFOP(fd,7), auth_dat[i].userid, 24); - WFIFOB(fd,31) = auth_dat[i].sex; - WFIFOL(fd,32) = auth_dat[i].logincount; - WFIFOL(fd,36) = auth_dat[i].state; - memcpy(WFIFOP(fd,40), auth_dat[i].error_message, 20); - memcpy(WFIFOP(fd,60), auth_dat[i].lastlogin, 24); - memcpy(WFIFOP(fd,84), auth_dat[i].last_ip, 16); - memcpy(WFIFOP(fd,100), auth_dat[i].email, 40); - WFIFOL(fd,140) = (unsigned long)auth_dat[i].connect_until_time; - WFIFOL(fd,144) = (unsigned long)auth_dat[i].ban_until_time; - WFIFOW(fd,148) = (uint16)strlen(auth_dat[i].memo); - if (auth_dat[i].memo[0]) { - memcpy(WFIFOP(fd,150), auth_dat[i].memo, strlen(auth_dat[i].memo)); - } - WFIFOSET(fd,150+strlen(auth_dat[i].memo)); - break; - } - } - if (i == auth_num) { - login_log("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n", - RFIFOL(fd,2), ip); - strncpy((char*)WFIFOP(fd,7), "", 24); - WFIFOW(fd,148) = 0; - WFIFOSET(fd,150); - } - RFIFOSKIP(fd,6); - break; - - case 0x7955: // Request to reload GM file (no answer) - login_log("'ladmin': Request to re-load GM configuration file (ip: %s).\n", ip); - read_gm_account(); - // send GM accounts to all char-servers - send_GM_accounts(-1); - RFIFOSKIP(fd,2); - break; - - default: - { - FILE *logfp; - char tmpstr[24]; - time_t raw_time; - logfp = fopen(login_log_unknown_packets_filename, "a"); - if (logfp) { - time(&raw_time); - strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time)); - fprintf(logfp, "%s: receiving of an unknown packet -> disconnection\n", tmpstr); - fprintf(logfp, "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %lu).\n", fd, ip, command, (unsigned long)RFIFOREST(fd)); - fprintf(logfp, "Detail (in hex):\n"); - fprintf(logfp, "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n"); - memset(tmpstr, '\0', sizeof(tmpstr)); - for(i = 0; i < RFIFOREST(fd); i++) { - if ((i & 15) == 0) - fprintf(logfp, "%04X ",i); - fprintf(logfp, "%02x ", RFIFOB(fd,i)); - if (RFIFOB(fd,i) > 0x1f) - tmpstr[i % 16] = RFIFOB(fd,i); - else - tmpstr[i % 16] = '.'; - if ((i - 7) % 16 == 0) // -8 + 1 - fprintf(logfp, " "); - else if ((i + 1) % 16 == 0) { - fprintf(logfp, " %s\n", tmpstr); - memset(tmpstr, '\0', sizeof(tmpstr)); - } - } - if (i % 16 != 0) { - for(j = i; j % 16 != 0; j++) { - fprintf(logfp, " "); - if ((j - 7) % 16 == 0) // -8 + 1 - fprintf(logfp, " "); - } - fprintf(logfp, " %s\n", tmpstr); - } - fprintf(logfp, "\n"); - fclose(logfp); - } - } - login_log("'ladmin': End of connection, unknown packet (ip: %s)\n", ip); - set_eof(fd); - ShowWarning("Remote administration has been disconnected (unknown packet).\n"); - return 0; - } - } - RFIFOSKIP(fd,RFIFOREST(fd)); - return 0; -} - -//-------------------------------------------- -// Test to know if an IP come from LAN or WAN. -//-------------------------------------------- -int lan_subnetcheck(uint32 ip) -{ - int i; - ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) ); - return ( i < subnet_count ) ? subnet[i].char_ip : 0; -} - -//---------------------------------------------------------------------------------------- -// Default packet parsing (normal players or administation/char-server connection requests) -//---------------------------------------------------------------------------------------- -int parse_login(int fd) -{ - struct mmo_account account; - int result, j; - unsigned int i; - uint32 ipl = session[fd]->client_addr; - char ip[16]; - - if (session[fd]->eof) { - do_close(fd); - return 0; - } - - ip2str(ipl, ip); - - while( RFIFOREST(fd) >= 2 ) - { - uint16 command = RFIFOW(fd,0); - - switch(command) - { - case 0x0200: // New alive packet: structure: 0x200 .24B. used to verify if client is always alive. - if (RFIFOREST(fd) < 26) - return 0; - RFIFOSKIP(fd,26); - break; - - case 0x0204: // New alive packet: structure: 0x204 .16B. (new ragexe from 22 june 2004) - if (RFIFOREST(fd) < 18) + case 0x0204: // New alive packet: structure: 0x204 .16B. (new ragexe from 22 june 2004) + if (RFIFOREST(fd) < 18) return 0; RFIFOSKIP(fd,18); break; @@ -2979,12 +1851,12 @@ int parse_login(int fd) case 0x0277: // New login packet (kRO 2006-04-24aSakexe langtype 0) case 0x02b0: // New login packet (kRO 2007-05-14aSakexe langtype 0) { - int packet_len = RFIFOREST(fd); // assume no other packet was sent + size_t packet_len = RFIFOREST(fd); // assume no other packet was sent - //Perform ip-ban check + // Perform ip-ban check if (!check_ip(ipl)) { - login_log("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip); + ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip); WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = 3; // 3 = Rejected from Server @@ -3004,18 +1876,19 @@ int parse_login(int fd) // S 01dd .l .24B .16B .B // S 0277 .l .24B .24B .29B .B // S 02b0 .l .24B .24B .30B .B - + memset(&account, 0, sizeof(account)); account.version = RFIFOL(fd,2); - if (!account.version) account.version = 1; //Force some version... + if( !account.version ) + account.version = 1; //Force some version... memcpy(account.userid,RFIFOP(fd,6),NAME_LENGTH); account.userid[23] = '\0'; remove_control_chars(account.userid); if (command != 0x01dd) { - login_log("Request for connection (non encryption mode) of %s (ip: %s).\n", account.userid, ip); + ShowStatus("Request for connection (non encryption mode) of %s (ip: %s).\n", account.userid, ip); memcpy(account.passwd, RFIFOP(fd,30), NAME_LENGTH); account.passwd[23] = '\0'; remove_control_chars(account.passwd); } else { - login_log("Request for connection (encryption mode) of %s (ip: %s).\n", account.userid, ip); + ShowStatus("Request for connection (encryption mode) of %s (ip: %s).\n", account.userid, ip); memcpy(account.passwd, RFIFOP(fd,30), 16); account.passwd[16] = '\0'; // binary data here } account.passwdenc = (command == 0x01dd) ? PASSWORDENC : 0; @@ -3026,8 +1899,7 @@ int parse_login(int fd) int gm_level = isGM(account.account_id); if( login_config.min_level_to_connect > gm_level ) { - login_log("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n", - login_config.min_level_to_connect, account.userid, gm_level, ip); + ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n", login_config.min_level_to_connect, account.userid, gm_level, ip); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed @@ -3035,30 +1907,22 @@ int parse_login(int fd) } else { - uint8 server_num = 0; + uint8 server_num, n; + uint32 subnet_char_ip; - WFIFOHEAD(fd,47+32*MAX_SERVERS); + server_num = 0; for( i = 0; i < MAX_SERVERS; ++i ) - { - if( session_isValid(server_fd[i]) ) - { - // Advanced subnet check [LuzZza] - uint32 subnet_char_ip = lan_subnetcheck(ipl); - WFIFOL(fd,47+server_num*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip); - WFIFOW(fd,47+server_num*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!] - memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20); - WFIFOW(fd,47+server_num*32+26) = server[i].users; - WFIFOW(fd,47+server_num*32+28) = server[i].maintenance; - WFIFOW(fd,47+server_num*32+30) = server[i].new_; + if( session_isValid(server[i].fd) ) server_num++; - } - } - if (server_num > 0) { // if at least 1 char-server + + if( server_num > 0 ) + {// if at least 1 char-server if (gm_level) ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", gm_level, account.userid); else ShowStatus("Connection of the account '%s' accepted.\n", account.userid); + WFIFOHEAD(fd,47+32*server_num); WFIFOW(fd,0) = 0x69; WFIFOW(fd,2) = 47+32*server_num; WFIFOL(fd,4) = account.login_id1; @@ -3066,8 +1930,24 @@ int parse_login(int fd) WFIFOL(fd,12) = account.login_id2; WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used) //memcpy(WFIFOP(fd,20), account.lastlogin, 24); // in old version, that was for name (not more used) + WFIFOW(fd,44) = 0; // unknown WFIFOB(fd,46) = account.sex; + for( i = 0, n = 0; i < MAX_SERVERS; ++i ) + { + if( !session_isValid(server[i].fd) ) + continue; + + subnet_char_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] + WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip); + WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!] + memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20); + WFIFOW(fd,47+n*32+26) = server[i].users; + WFIFOW(fd,47+n*32+28) = server[i].maintenance; + WFIFOW(fd,47+n*32+30) = server[i].new_; + n++; + } WFIFOSET(fd,47+32*server_num); + if (auth_fifo_pos >= AUTH_FIFO_SIZE) auth_fifo_pos = 0; auth_fifo[auth_fifo_pos].account_id = account.account_id; @@ -3077,9 +1957,11 @@ int parse_login(int fd) auth_fifo[auth_fifo_pos].delflag = 0; auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; auth_fifo_pos++; - } else { // if no char-server, don't send void list of servers, just disconnect the player with proper message + } + else + {// if no char-server, don't send void list of servers, just disconnect the player with proper message ShowStatus("Connection refused: there is no char-server online (account: %s, ip: %s).\n", account.userid, ip); - login_log("Connection refused: there is no char-server online (account: %s, ip: %s).\n", account.userid, ip); + WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOSET(fd,3); @@ -3091,7 +1973,9 @@ int parse_login(int fd) WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = (uint8)result; - if( result == 6 ) + if( result != 6 ) + memset(WFIFOP(fd,3), '\0', 20); + else {// 6 = Your are Prohibited to log in until %s char tmpstr[20]; time_t ban_until_time; @@ -3100,8 +1984,6 @@ int parse_login(int fd) strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time)); safestrncpy((char*)WFIFOP(fd,3), tmpstr, 20); // ban timestamp goes here } - else - memset(WFIFOP(fd,3), '\0', 20); WFIFOSET(fd,23); } @@ -3122,13 +2004,13 @@ int parse_login(int fd) CREATE(ld, struct login_session_data, 1); session[fd]->session_data = ld; - + // Creation of the coding key memset(ld->md5key, '\0', sizeof(ld->md5key)); ld->md5keylen = (uint16)(12 + rand() % 4); for( i = 0; i < ld->md5keylen; ++i ) ld->md5key[i] = (char)(1 + rand() % 255); - + WFIFOHEAD(fd,4 + ld->md5keylen); WFIFOW(fd,0) = 0x01dc; WFIFOW(fd,2) = 4 + ld->md5keylen; @@ -3146,7 +2028,7 @@ int parse_login(int fd) char* server_name; uint32 server_ip; uint16 server_port; - + memset(&account, 0, sizeof(account)); safestrncpy(account.userid, (char*)RFIFOP(fd,2), NAME_LENGTH); remove_control_chars(account.userid); safestrncpy(account.passwd, (char*)RFIFOP(fd,26), NAME_LENGTH); remove_control_chars(account.passwd); @@ -3154,15 +2036,13 @@ int parse_login(int fd) server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0'; remove_control_chars(server_name); server_ip = ntohl(RFIFOL(fd, 54)); server_port = ntohs(RFIFOW(fd, 58)); - + ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, account.userid, account.passwd, ip); - login_log("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, account.userid, account.passwd, ip); - + result = mmo_auth(&account, fd); - if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1 ) + if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server[account.account_id].fd == -1 ) { ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); - login_log("Connection of the char-server '%s' accepted.\n", server_name); memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); server[account.account_id].ip = ntohl(RFIFOL(fd,54)); server[account.account_id].port = ntohs(RFIFOW(fd,58)); @@ -3170,23 +2050,22 @@ int parse_login(int fd) server[account.account_id].users = 0; server[account.account_id].maintenance = RFIFOW(fd,82); server[account.account_id].new_ = RFIFOW(fd,84); - server_fd[account.account_id] = fd; - - WFIFOHEAD(fd,3); + server[account.account_id].fd = fd; + + WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); - + session[fd]->func_parse = parse_fromchar; session[fd]->client_addr = 0; realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - + send_GM_accounts(fd); // send GM account to char-server } else { ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name); - login_log("Connection of the char-server '%s' REFUSED.\n", server_name); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 3; @@ -3198,7 +2077,7 @@ int parse_login(int fd) return 0; case 0x7530: // Server version information request - login_log("Sending of the server version (ip: %s)\n", ip); + ShowStatus("Sending server version information to ip: %s\n", ip); WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x7531; WFIFOB(fd,2) = ATHENA_MAJOR_VERSION; @@ -3214,7 +2093,7 @@ int parse_login(int fd) break; case 0x7532: // Request to end connection - login_log("End of connection (ip: %s)\n", ip); + ShowStatus("End of connection (ip: %s)\n", ip); set_eof(fd); return 0; @@ -3224,7 +2103,7 @@ int parse_login(int fd) WFIFOW(fd,0) = 0x7919; WFIFOB(fd,2) = 1; if (!check_ladminip(session[fd]->client_addr)) { - login_log("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s).\n", ip); + ShowNotice("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s).\n", ip); } else { struct login_session_data *ld = (struct login_session_data*)session[fd]->session_data; if (RFIFOW(fd,2) == 0) { // non encrypted password @@ -3233,14 +2112,13 @@ int parse_login(int fd) password[24] = '\0'; remove_control_chars(password); if( !admin_state ) - login_log("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)\n", password, ip); + ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)\n", password, ip); else if( strcmp(password, admin_pass) != 0) - login_log("'ladmin'-login: Connection in administration mode REFUSED - invalid password (non encrypted password: %s, ip: %s)\n", password, ip); + ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - invalid password (non encrypted password: %s, ip: %s)\n", password, ip); else { // If remote administration is enabled and password sent by client matches password read from login server configuration file - login_log("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)\n", password, ip); - ShowNotice("Connection of a remote administration accepted (non encrypted password).\n"); + ShowNotice("'ladmin'-login: Connection in administration mode accepted (non encrypted password: %s, ip: %s)\n", password, ip); WFIFOB(fd,2) = 0; session[fd]->func_parse = parse_admin; } @@ -3256,13 +2134,13 @@ int parse_login(int fd) } MD5_String2binary(md5str, md5bin); if( !admin_state ) - login_log("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (encrypted password, ip: %s)\n", ip); + ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (encrypted password, ip: %s)\n", ip); else if( memcmp(md5bin, RFIFOP(fd,4), 16) != 0 ) - login_log("'ladmin'-login: Connection in administration mode REFUSED - invalid password (encrypted password, ip: %s)\n", ip); + ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - invalid password (encrypted password, ip: %s)\n", ip); else { // If remote administration is enabled and password hash sent by client matches hash of password read from login server configuration file - login_log("'ladmin'-login: Connection in administration mode accepted (encrypted password, ip: %s)\n", ip); + ShowNotice("'ladmin'-login: Connection in administration mode accepted (encrypted password, ip: %s)\n", ip); ShowNotice("Connection of a remote administration accepted (encrypted password).\n"); WFIFOB(fd,2) = 0; session[fd]->func_parse = parse_admin; @@ -3316,7 +2194,7 @@ int parse_login(int fd) fclose(logfp); } } - login_log("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command); + ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command); set_eof(fd); return 0; } @@ -3338,7 +2216,6 @@ int parse_console(char* buf) sscanf(buf, "%[^\n]", command); ShowInfo("Console command :%s", command); - login_log("Console command :%s\n", command); if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || @@ -3386,7 +2263,7 @@ int login_lan_config_read(const char *lancfgName) FILE *fp; int line_num = 0; char line[1024], w1[64], w2[64], w3[64], w4[64]; - + if((fp = fopen(lancfgName, "r")) == NULL) { ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName); return 1; @@ -3417,7 +2294,7 @@ int login_lan_config_read(const char *lancfgName) subnet[subnet_count].char_ip = str2ip(w3); subnet[subnet_count].map_ip = str2ip(w4); - if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip&subnet[subnet_count].mask) ) + if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip & subnet[subnet_count].mask) ) { ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4); continue; @@ -3425,7 +2302,6 @@ int login_lan_config_read(const char *lancfgName) subnet_count++; } - } ShowStatus("Read information about %d subnetworks.\n", subnet_count); @@ -3524,18 +2400,12 @@ int login_config_read(const char* cfgName) gm_account_filename_check_timer = atoi(w2); } else if (strcmpi(w1, "log_login") == 0) { login_config.log_login = (bool)config_switch(w2); - } else if (strcmpi(w1, "login_log_filename") == 0) { - memset(login_log_filename, 0, sizeof(login_log_filename)); - strncpy(login_log_filename, w2, sizeof(login_log_filename)); - login_log_filename[sizeof(login_log_filename)-1] = '\0'; } else if (strcmpi(w1, "login_log_unknown_packets_filename") == 0) { memset(login_log_unknown_packets_filename, 0, sizeof(login_log_unknown_packets_filename)); strncpy(login_log_unknown_packets_filename, w2, sizeof(login_log_unknown_packets_filename)); login_log_unknown_packets_filename[sizeof(login_log_unknown_packets_filename)-1] = '\0'; } else if (strcmpi(w1, "save_unknown_packets") == 0) { save_unknown_packets = config_switch(w2); - } else if (strcmpi(w1, "add_to_unlimited_account") == 0) { - add_to_unlimited_account = config_switch(w2); } else if (strcmpi(w1, "start_limited_time") == 0) { start_limited_time = atoi(w2); } else if (strcmpi(w1, "order") == 0) { @@ -3659,16 +2529,6 @@ void display_conf_warnings(void) level_new_gm = 60; } - if (login_config.new_account_flag != 0 && login_config.new_account_flag != 1) { - ShowWarning("Invalid value for new_account parameter -> setting to 0 (no new account).\n"); - login_config.new_account_flag = 0; - } - - if (login_config.login_port < 1024) { - ShowWarning("Invalid value for login_port parameter -> setting to 6900 (default).\n"); - login_config.login_port = 6900; - } - if (gm_account_filename_check_timer < 0) { ShowWarning("Invalid value for gm_account_filename_check_timer parameter. Setting to 15 sec (default).\n"); gm_account_filename_check_timer = 15; @@ -3677,11 +2537,6 @@ void display_conf_warnings(void) gm_account_filename_check_timer = 2; } - if (save_unknown_packets != 0 && save_unknown_packets != 1) { - ShowWarning("Invalid value for save_unknown_packets parameter -> setting to 0-no save.\n"); - save_unknown_packets = 0; - } - if (login_config.min_level_to_connect < 0) { // 0: all players, 1-99 at least gm level x ShowWarning("Invalid value for min_level_to_connect (%d) parameter -> setting 0 (any player).\n", login_config.min_level_to_connect); login_config.min_level_to_connect = 0; @@ -3690,12 +2545,6 @@ void display_conf_warnings(void) login_config.min_level_to_connect = 99; } - if (add_to_unlimited_account != 0 && add_to_unlimited_account != 1) { // 0: no, 1: yes - ShowWarning("Invalid value for add_to_unlimited_account parameter\n"); - ShowWarning(" -> setting to 0 (impossible to add a time to an unlimited account).\n"); - add_to_unlimited_account = 0; - } - if (start_limited_time < -1) { // -1: create unlimited account, 0 or more: additionnal sec from now to create limited time ShowWarning("Invalid value for start_limited_time parameter\n"); ShowWarning(" -> setting to -1 (new accounts are created with unlimited time).\n"); @@ -3725,133 +2574,6 @@ void display_conf_warnings(void) return; } -//------------------------------- -// Save configuration in log file -//------------------------------- -void save_config_in_log(void) -{ - int i; - - // a newline in the log... - login_log(""); - login_log("The login-server starting...\n"); - - // save configuration in log file - login_log("The configuration of the server is set:\n"); - - if( !admin_state ) - login_log("- with no remote administration.\n"); - else if (admin_pass[0] == '\0') - login_log("- with a remote administration with a VOID password.\n"); - else if (strcmp(admin_pass, "admin") == 0) - login_log("- with a remote administration with the DEFAULT password.\n"); - else - login_log("- with a remote administration with the password of %d character(s).\n", strlen(admin_pass)); - if (access_ladmin_allownum == 0 || (access_ladmin_allownum == 1 && access_ladmin_allow[0] == '\0')) { - login_log("- to accept any IP for remote administration\n"); - } else { - login_log("- to accept following IP for remote administration:\n"); - for(i = 0; i < access_ladmin_allownum; i++) - login_log(" %s\n", (char *)(access_ladmin_allow + i * ACO_STRSIZE)); - } - - if (gm_pass[0] == '\0') - login_log("- with a VOID 'To GM become' password (gm_pass).\n"); - else if (strcmp(gm_pass, "gm") == 0) - login_log("- with the DEFAULT 'To GM become' password (gm_pass).\n"); - else - login_log("- with a 'To GM become' password (gm_pass) of %d character(s).\n", strlen(gm_pass)); - if (level_new_gm == 0) - login_log("- to refuse any creation of GM with @gm.\n"); - else - login_log("- to create GM with level '%d' when @gm is used.\n", level_new_gm); - - if (login_config.new_account_flag == 1) - login_log("- to ALLOW new users (with _F/_M).\n"); - else - login_log("- to NOT ALLOW new users (with _F/_M).\n"); - login_log("- with port: %d.\n", login_config.login_port); - login_log("- with the accounts file name: '%s'.\n", account_filename); - login_log("- with the GM accounts file name: '%s'.\n", GM_account_filename); - if (gm_account_filename_check_timer == 0) - login_log("- to NOT check GM accounts file modifications.\n"); - else - login_log("- to check GM accounts file modifications every %d seconds.\n", gm_account_filename_check_timer); - - if (login_config.use_md5_passwds == 0) - login_log("- to save password in plain text.\n"); - else - login_log("- to save password with MD5 encrypting.\n"); - - // not necessary to log the 'login_log_filename', we are inside :) - - login_log("- with the unknown packets file name: '%s'.\n", login_log_unknown_packets_filename); - if (save_unknown_packets) - login_log("- to SAVE all unkown packets.\n"); - else - login_log("- to SAVE only unkown packets sending by a char-server or a remote administration.\n"); - - if (login_config.min_level_to_connect == 0) // 0: all players, 1-99 at least gm level x - login_log("- with no minimum level for connection.\n"); - else if (login_config.min_level_to_connect == 99) - login_log("- to accept only GM with level 99.\n"); - else - login_log("- to accept only GM with level %d or more.\n", login_config.min_level_to_connect); - - if (add_to_unlimited_account) - login_log("- to authorize adjustment (with timeadd ladmin) on an unlimited account.\n"); - else - login_log("- to refuse adjustment (with timeadd ladmin) on an unlimited account. You must use timeset (ladmin command) before.\n"); - - if (start_limited_time < 0) - login_log("- to create new accounts with an unlimited time.\n"); - else if (start_limited_time == 0) - login_log("- to create new accounts with a limited time: time of creation.\n"); - else - login_log("- to create new accounts with a limited time: time of creation + %d second(s).\n", start_limited_time); - - if (access_order == ACO_DENY_ALLOW) { - if (access_denynum == 0) { - login_log("- with the IP security order: 'deny,allow' (allow if not deny). You refuse no IP.\n"); - } else if (access_denynum == 1 && access_deny[0] == '\0') { - login_log("- with the IP security order: 'deny,allow' (allow if not deny). You refuse ALL IP.\n"); - } else { - login_log("- with the IP security order: 'deny,allow' (allow if not deny). Refused IP are:\n"); - for(i = 0; i < access_denynum; i++) - login_log(" %s\n", (char *)(access_deny + i * ACO_STRSIZE)); - } - } else if (access_order == ACO_ALLOW_DENY) { - if (access_allownum == 0) { - login_log("- with the IP security order: 'allow,deny' (deny if not allow). But, NO IP IS AUTHORISED!\n"); - } else if (access_allownum == 1 && access_allow[0] == '\0') { - login_log("- with the IP security order: 'allow,deny' (deny if not allow). You authorise ALL IP.\n"); - } else { - login_log("- with the IP security order: 'allow,deny' (deny if not allow). Authorised IP are:\n"); - for(i = 0; i < access_allownum; i++) - login_log(" %s\n", (char *)(access_allow + i * ACO_STRSIZE)); - } - } else { // ACO_MUTUAL_FAILTURE - login_log("- with the IP security order: 'mutual-failture' (allow if in the allow list and not in the deny list).\n"); - if (access_allownum == 0) { - login_log(" But, NO IP IS AUTHORISED!\n"); - } else if (access_denynum == 1 && access_deny[0] == '\0') { - login_log(" But, you refuse ALL IP!\n"); - } else { - if (access_allownum == 1 && access_allow[0] == '\0') { - login_log(" You authorise ALL IP.\n"); - } else { - login_log(" Authorised IP are:\n"); - for(i = 0; i < access_allownum; i++) - login_log(" %s\n", (char *)(access_allow + i * ACO_STRSIZE)); - } - login_log(" Refused IP are:\n"); - for(i = 0; i < access_denynum; i++) - login_log(" %s\n", (char *)(access_deny + i * ACO_STRSIZE)); - } - - } -} - void login_set_defaults() { login_config.login_ip = INADDR_ANY; @@ -3894,16 +2616,14 @@ void do_final(void) if(access_allow) aFree(access_allow); if(access_deny) aFree(access_deny); for (i = 0; i < MAX_SERVERS; i++) { - if ((fd = server_fd[i]) >= 0) { - server_fd[i] = -1; + if ((fd = server[i].fd) >= 0) { + server[i].fd = -1; memset(&server[i], 0, sizeof(struct mmo_char_server)); do_close(fd); } } do_close(login_fd); - login_log("----End of login-server (normal end with closing of all files).\n"); - if(log_fp) fclose(log_fp); ShowStatus("Finished.\n"); @@ -3927,14 +2647,13 @@ void set_server_type(void) //------------------------------ int do_init(int argc, char** argv) { - int i, j; + int i; login_set_defaults(); // read login-server configuration login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME); display_conf_warnings(); // not in login_config_read, because we can use 'import' option, and display same message twice or more - save_config_in_log(); // not before, because log file name can be changed login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME); srand((unsigned int)time(NULL)); @@ -3943,7 +2662,7 @@ int do_init(int argc, char** argv) auth_fifo[i].delflag = 1; for( i = 0; i < MAX_SERVERS; i++ ) - server_fd[i] = -1; + server[i].fd = -1; // Online user database init online_db = idb_alloc(DB_OPT_RELEASE_DATA); @@ -3961,14 +2680,11 @@ int do_init(int argc, char** argv) add_timer_func_list(check_auth_sync, "check_auth_sync"); add_timer_interval(gettick() + 60000, check_auth_sync, 0, 0, 60000); // every 60 sec we check if we must save accounts file (only if necessary to save) - // add timer to check GM accounts file modification - j = gm_account_filename_check_timer; - if (j == 0) // if we would not to check, we check every 60 sec, just to have timer (if we change timer, is was not necessary to check if timer already exists) - j = 60; - // every x sec we check if gm file has been changed - add_timer_func_list(check_GM_file, "check_GM_file"); - add_timer_interval(gettick() + j * 1000, check_GM_file, 0, 0, j * 1000); + if( gm_account_filename_check_timer ) { + add_timer_func_list(check_GM_file, "check_GM_file"); + add_timer_interval(gettick() + gm_account_filename_check_timer * 1000, check_GM_file, 0, 0, gm_account_filename_check_timer * 1000); + } // every 10 minutes cleanup online account db. add_timer_func_list(online_data_cleanup, "online_data_cleanup"); @@ -3990,7 +2706,6 @@ int do_init(int argc, char** argv) // server port open & binding login_fd = make_listen_bind(login_config.login_ip, login_config.login_port); - login_log("The login-server is ready (Server is listening on the port %d).\n", login_config.login_port); ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port); return 0; diff --git a/src/login/login.h b/src/login/login.h index 405b3fab2..ab6396a5d 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -4,7 +4,7 @@ #ifndef _LOGIN_H_ #define _LOGIN_H_ -#include "../common/mmo.h" +#include "../common/mmo.h" // NAME_LENGTH #define LOGIN_CONF_NAME "conf/login_athena.conf" #define LAN_CONF_NAME "conf/subnet_athena.conf" @@ -24,10 +24,12 @@ struct mmo_account { long char_id; char lastlogin[24]; char sex; + //uint8 level; }; struct mmo_char_server { char name[20]; + int fd; uint32 ip; uint16 port; uint16 users; // user count on this server @@ -35,4 +37,62 @@ struct mmo_char_server { uint16 new_; // allows creating new chars? }; +extern struct Login_Config { + + uint32 login_ip; // the address to bind to + uint16 login_port; // the port to bind to + unsigned int ip_sync_interval; // interval (in minutes) to execute a DNS/IP update (for dynamic IPs) + bool log_login; // whether to log login server actions or not + char date_format[32]; // date format used in messages + bool console; // console input system enabled? + bool new_account_flag; // autoregistration via _M/_F ? +// bool case_sensitive; // are logins case sensitive ? + bool use_md5_passwds; // work with password hashes instead of plaintext passwords? +// bool login_gm_read; // should the login server handle info about gm accounts? + int min_level_to_connect; // minimum level of player/GM (0: player, 1-99: GM) to connect + bool online_check; // reject incoming players that are already registered as online ? + bool check_client_version; // check the clientversion set in the clientinfo ? + int client_version_to_connect; // the client version needed to connect (if checking is enabled) + +// bool ipban; // perform IP blocking (via contents of `ipbanlist`) ? +// bool dynamic_pass_failure_ban; // automatic IP blocking due to failed login attemps ? +// unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures +// unsigned int dynamic_pass_failure_ban_limit; // number of failures needed to trigger the ipban +// unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban + bool use_dnsbl; // dns blacklist blocking ? + char dnsbl_servs[1024]; // comma-separated list of dnsbl servers + +} login_config; + +// TXT-specific account database +// holds info about all existing accounts (entire contents of account.txt) +extern struct auth_data { + int account_id; + uint8 sex; // 0, 1, 2 + char userid[24]; + char pass[32+1]; // 23+1 for normal, 32+1 for md5-ed passwords + char lastlogin[24]; + int logincount; + uint32 state; // packet 0x006a value + 1 (0: compte OK) + char email[40]; // e-mail (by default: a@a.com) + char error_message[20]; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a) + time_t ban_until_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban) + time_t connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + char last_ip[16]; // save of last IP of connection + char memo[255]; // a memo field + int account_reg2_num; + struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server) +} *auth_dat; + +// stores auth information of incoming clients +// used during charserver auth validation process +#define AUTH_FIFO_SIZE 256 +extern struct _auth_fifo { + int account_id; + uint32 login_id1, login_id2; + uint32 ip; + uint8 sex; + bool delflag; +} auth_fifo[AUTH_FIFO_SIZE]; + #endif /* _LOGIN_H_ */ diff --git a/src/login_sql/login.c b/src/login_sql/login.c index f72590bac..f63961f82 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -20,36 +20,10 @@ #include #include // for stat/lstat/fstat -struct Login_Config { - - uint32 login_ip; // the address to bind to - uint16 login_port; // the port to bind to - unsigned int ip_sync_interval; // interval (in minutes) to execute a DNS/IP update (for dynamic IPs) - bool log_login; // whether to log login server actions or not - char date_format[32]; // date format used in messages - bool console; // console input system enabled? - bool new_account_flag; // autoregistration via _M/_F ? - bool case_sensitive; // are logins case sensitive ? - bool use_md5_passwds; // work with password hashes instead of plaintext passwords? - bool login_gm_read; // should the login server handle info about gm accounts? - int min_level_to_connect; // minimum level of player/GM (0: player, 1-99: GM) to connect - bool online_check; // reject incoming players that are already registered as online ? - bool check_client_version; // check the clientversion set in the clientinfo ? - int client_version_to_connect; // the client version needed to connect (if checking is enabled) - - bool ipban; // perform IP blocking (via contents of `ipbanlist`) ? - bool dynamic_pass_failure_ban; // automatic IP blocking due to failed login attemps ? - unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures - unsigned int dynamic_pass_failure_ban_limit; // number of failures needed to trigger the ipban - unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban - bool use_dnsbl; // dns blacklist blocking ? - char dnsbl_servs[1024]; // comma-separated list of dnsbl servers - -} login_config; +struct Login_Config login_config; int login_fd; // login server socket #define MAX_SERVERS 30 -int server_fd[MAX_SERVERS]; // char server sockets struct mmo_char_server server[MAX_SERVERS]; // char server data // Advanced subnet check [LuzZza] @@ -98,25 +72,22 @@ struct login_session_data { char md5key[20]; }; -#define AUTH_FIFO_SIZE 256 -struct _auth_fifo { - int account_id; - uint32 login_id1, login_id2; - uint32 ip; - uint8 sex; - bool delflag; -} auth_fifo[AUTH_FIFO_SIZE]; +// auth information of incoming clients +struct _auth_fifo auth_fifo[AUTH_FIFO_SIZE]; int auth_fifo_pos = 0; +//----------------------------------------------------- +// Online User Database [Wizputer] +//----------------------------------------------------- + struct online_login_data { int account_id; int waiting_disconnect; int char_server; }; -//----------------------------------------------------- - static DBMap* online_db; // int account_id -> struct online_login_data* +static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); static void* create_online_user(DBKey key, va_list args) { @@ -128,13 +99,6 @@ static void* create_online_user(DBKey key, va_list args) return p; } -int charif_sendallwos(int sfd, uint8* buf, size_t len); -static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); - -//----------------------------------------------------- -// Online User Database [Wizputer] -//----------------------------------------------------- - void add_online_user(int char_server, int account_id) { struct online_login_data* p; @@ -172,13 +136,26 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data return 0; } -static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) +//-------------------------------------------------------------------- +// Packet send to all char-servers, except one (wos: without our self) +//-------------------------------------------------------------------- +int charif_sendallwos(int sfd, uint8* buf, size_t len) { - uint8 buf[2]; - ShowInfo("IP Sync in progress...\n"); - WBUFW(buf,0) = 0x2735; - charif_sendallwos(-1, buf, 2); - return 0; + int i, c; + + for( i = 0, c = 0; i < MAX_SERVERS; ++i ) + { + int fd = server[i].fd; + if( session_isValid(fd) && fd != sfd ) + { + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + ++c; + } + } + + return c; } //----------------------------------------------------- @@ -331,7 +308,7 @@ void mmo_db_close(void) for( i = 0; i < MAX_SERVERS; ++i ) { - fd = server_fd[i]; + fd = server[i].fd; if( session_isValid(fd) ) {// Clean only data related to servers we are connected to. [Skotlex] if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `sstatus` WHERE `index` = '%d'", i) ) @@ -346,30 +323,18 @@ void mmo_db_close(void) do_close(login_fd); } - -//-------------------------------------------------------------------- -// Packet send to all char-servers, except one (wos: without our self) -//-------------------------------------------------------------------- -int charif_sendallwos(int sfd, uint8* buf, size_t len) +//----------------------------------------------------- +// periodic ip address synchronization +//----------------------------------------------------- +static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) { - int i, c; - - for( i = 0, c = 0; i < MAX_SERVERS; ++i ) - { - int fd = server_fd[i]; - if( session_isValid(fd) && fd != sfd ) - { - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - ++c; - } - } - - return c; + uint8 buf[2]; + ShowInfo("IP Sync in progress...\n"); + WBUFW(buf,0) = 0x2735; + charif_sendallwos(-1, buf, 2); + return 0; } - //----------------------------------------------------- // encrypted/unencrypted password check //----------------------------------------------------- @@ -645,7 +610,7 @@ int parse_fromchar(int fd) char ip[16]; ip2str(ipl, ip); - ARR_FIND( 0, MAX_SERVERS, id, server_fd[id] == fd ); + ARR_FIND( 0, MAX_SERVERS, id, server[id].fd == fd ); if( id == MAX_SERVERS ) {// not a char server set_eof(fd); @@ -656,7 +621,7 @@ int parse_fromchar(int fd) if( session[fd]->eof ) { ShowStatus("Char-server '%s' has disconnected.\n", server[id].name); - server_fd[id] = -1; + server[id].fd = -1; memset(&server[id], 0, sizeof(struct mmo_char_server)); online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `sstatus` WHERE `index`='%d'", id) ) @@ -673,6 +638,7 @@ int parse_fromchar(int fd) { case 0x2709: // request from map-server via char-server to reload GM accounts + ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip); if( login_config.log_login ) { if( SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, ipl, server[id].name) ) @@ -689,21 +655,18 @@ int parse_fromchar(int fd) return 0; { int account_id = RFIFOL(fd,2); - for( i = 0; i < AUTH_FIFO_SIZE; ++i ) - { - if( auth_fifo[i].account_id == RFIFOL(fd,2) && - auth_fifo[i].login_id1 == RFIFOL(fd,6) && - auth_fifo[i].login_id2 == RFIFOL(fd,10) && - auth_fifo[i].sex == RFIFOB(fd,14) && - auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) && - !auth_fifo[i].delflag) - { - auth_fifo[i].delflag = 1; - break; - } - } - - if( i != AUTH_FIFO_SIZE && account_id > 0 ) + ARR_FIND( 0, AUTH_FIFO_SIZE, i, + auth_fifo[i].account_id == RFIFOL(fd,2) && + auth_fifo[i].login_id1 == RFIFOL(fd,6) && + auth_fifo[i].login_id2 == RFIFOL(fd,10) && + auth_fifo[i].sex == RFIFOB(fd,14) && + auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) && + !auth_fifo[i].delflag ); + + if( i < AUTH_FIFO_SIZE ) + auth_fifo[i].delflag = 1; + + if( i < AUTH_FIFO_SIZE && account_id > 0 ) {// send ack uint32 connect_until_time; char email[40]; @@ -737,7 +700,8 @@ int parse_fromchar(int fd) WFIFOSET(fd,51); } else - {// authentification not found + {// authentication not found + ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip); WFIFOHEAD(fd,51); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; @@ -752,7 +716,7 @@ int parse_fromchar(int fd) break; case 0x2714: - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; // how many users on world? (update) @@ -906,9 +870,8 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 10) return 0; { - int account_id, state; - account_id = RFIFOL(fd,2); - state = RFIFOL(fd,6); + int account_id = RFIFOL(fd,2); + int state = RFIFOL(fd,6); if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) ) Sql_ShowDebug(sql_handle); else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) @@ -990,7 +953,7 @@ int parse_fromchar(int fd) break; case 0x2727: // Change of sex (sex is reversed) - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; { int account_id; @@ -1099,14 +1062,14 @@ int parse_fromchar(int fd) } case 0x272b: // Set account_id to online [Wizputer] - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; add_online_user(id, RFIFOL(fd,2)); RFIFOSKIP(fd,6); break; case 0x272c: // Set account_id to offline [Wizputer] - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; remove_online_user(RFIFOL(fd,2)); RFIFOSKIP(fd,6); @@ -1179,7 +1142,7 @@ int parse_fromchar(int fd) break; case 0x2736: // WAN IP update from char-server - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; server[id].ip = ntohl(RFIFOL(fd,2)); ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip)); @@ -1256,14 +1219,14 @@ int parse_login(int fd) uint32 ipl = session[fd]->client_addr; char ip[16]; - ip2str(ipl, ip); - if( session[fd]->eof ) { do_close(fd); return 0; } + ip2str(ipl, ip); + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); @@ -1287,11 +1250,12 @@ int parse_login(int fd) case 0x0277: // New login packet (kRO 2006-04-24aSakexe langtype 0) case 0x02b0: // New login packet (kRO 2007-05-14aSakexe langtype 0) { - size_t packet_len = RFIFOREST(fd); + size_t packet_len = RFIFOREST(fd); // assume no other packet was sent // Perform ip-ban check if( login_config.ipban && login_ip_ban_check(ipl) ) { + ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip); WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = 3; // 3 = Rejected from Server @@ -1326,6 +1290,7 @@ int parse_login(int fd) { // auth success if( login_config.min_level_to_connect > account.level ) { + ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d, ip: %s).\n", login_config.min_level_to_connect, account.userid, account.level, ip); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed @@ -1333,32 +1298,24 @@ int parse_login(int fd) } else { - uint8 server_num = 0; + uint8 server_num, n; + uint32 subnet_char_ip; - if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, esc_userid) ) - Sql_ShowDebug(sql_handle); - if( account.level ) - ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid); - else - ShowStatus("Connection of the account '%s' accepted.\n", account.userid); - - WFIFOHEAD(fd,47+32*MAX_SERVERS); + server_num = 0; for( i = 0; i < MAX_SERVERS; ++i ) - { - if( session_isValid(server_fd[i]) ) - { - // Advanced subnet check [LuzZza] - uint32 subnet_char_ip = lan_subnetcheck(ipl); - WFIFOL(fd,47+server_num*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip); - WFIFOW(fd,47+server_num*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!] - memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20); - WFIFOW(fd,47+server_num*32+26) = server[i].users; - WFIFOW(fd,47+server_num*32+28) = server[i].maintenance; - WFIFOW(fd,47+server_num*32+30) = server[i].new_; + if( session_isValid(server[i].fd) ) server_num++; - } - } - if (server_num > 0) { // if at least 1 char-server + + if( server_num > 0 ) + {// if at least 1 char-server + if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, esc_userid) ) + Sql_ShowDebug(sql_handle); + if( account.level ) + ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid); + else + ShowStatus("Connection of the account '%s' accepted.\n", account.userid); + + WFIFOHEAD(fd,47+32*server_num); WFIFOW(fd,0) = 0x69; WFIFOW(fd,2) = 47+32*server_num; WFIFOL(fd,4) = account.login_id1; @@ -1366,8 +1323,24 @@ int parse_login(int fd) WFIFOL(fd,12) = account.login_id2; WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used) //memcpy(WFIFOP(fd,20), account.lastlogin, 24); // in old version, that was for name (not more used) + WFIFOW(fd,44) = 0; // unknown WFIFOB(fd,46) = account.sex; + for( i = 0, n = 0; i < MAX_SERVERS; ++i ) + { + if( !session_isValid(server[i].fd) ) + continue; + + subnet_char_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] + WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip); + WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!] + memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20); + WFIFOW(fd,47+n*32+26) = server[i].users; + WFIFOW(fd,47+n*32+28) = server[i].maintenance; + WFIFOW(fd,47+n*32+30) = server[i].new_; + n++; + } WFIFOSET(fd,47+32*server_num); + if (auth_fifo_pos >= AUTH_FIFO_SIZE) auth_fifo_pos = 0; auth_fifo[auth_fifo_pos].account_id = account.account_id; @@ -1377,7 +1350,11 @@ int parse_login(int fd) auth_fifo[auth_fifo_pos].delflag = 0; auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; auth_fifo_pos++; - } else { // if no char-server, don't send void list of servers, just disconnect the player with proper message + } + else + {// if no char-server, don't send void list of servers, just disconnect the player with proper message + ShowStatus("Connection refused: there is no char-server online (account: %s, ip: %s).\n", account.userid, ip); + WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOSET(fd,3); @@ -1445,7 +1422,9 @@ int parse_login(int fd) WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = (uint8)result; - if( result == 6 ) + if( result != 6 ) + memset(WFIFOP(fd,3), '\0', 20); + else {// 6 = Your are Prohibited to log in until %s if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = %s '%s'", login_db, login_db_userid, (login_config.case_sensitive ? "BINARY" : ""), esc_userid) ) Sql_ShowDebug(sql_handle); @@ -1461,8 +1440,6 @@ int parse_login(int fd) strftime((char*)WFIFOP(fd,3), 20, login_config.date_format, localtime(&ban_until_time)); } } - else - memset(WFIFOP(fd,3), '\0', 20); WFIFOSET(fd,23); } @@ -1526,7 +1503,7 @@ int parse_login(int fd) Sql_ShowDebug(sql_handle); result = mmo_auth(&account, fd); - if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1 ) + if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server[account.account_id].fd == -1 ) { ShowStatus("Connection of the char-server '%s' accepted.\n", esc_server_name); memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); @@ -1536,7 +1513,7 @@ int parse_login(int fd) server[account.account_id].users = 0; server[account.account_id].maintenance = RFIFOW(fd,82); server[account.account_id].new_ = RFIFOW(fd,84); - server_fd[account.account_id] = fd; + server[account.account_id].fd = fd; WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; @@ -1560,14 +1537,12 @@ int parse_login(int fd) WFIFOB(fd,2) = 3; WFIFOSET(fd,3); } - + } RFIFOSKIP(fd,86); return 0; - } case 0x7530: // Server version information request - { - ShowInfo ("Athena version check...\n"); + ShowStatus("Sending server version information to ip: %s\n", ip); WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x7531; WFIFOB(fd,2) = ATHENA_MAJOR_VERSION; @@ -1580,7 +1555,6 @@ int parse_login(int fd) WFIFOSET(fd,10); RFIFOSKIP(fd,2); - } break; case 0x7532: // Request to end connection @@ -1589,7 +1563,7 @@ int parse_login(int fd) break; default: - ShowStatus("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, RFIFOW(fd,0)); + ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command); set_eof(fd); return 0; } @@ -1618,7 +1592,7 @@ int parse_console(char* buf) strcmpi("end", command) == 0 ) runflag = 0; else - if( strcmpi("alive", command) == 0 || + if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 ) ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n"); else @@ -1931,7 +1905,7 @@ int do_init(int argc, char** argv) auth_fifo[i].delflag = 1; for( i = 0; i < MAX_SERVERS; i++ ) - server_fd[i] = -1; + server[i].fd = -1; // Online user database init online_db = idb_alloc(DB_OPT_RELEASE_DATA); diff --git a/src/login_sql/login.h b/src/login_sql/login.h index bc6337f42..b67d202cb 100644 --- a/src/login_sql/login.h +++ b/src/login_sql/login.h @@ -4,6 +4,8 @@ #ifndef _LOGIN_SQL_H_ #define _LOGIN_SQL_H_ +#include "../common/mmo.h" // NAME_LENGTH + #define LOGIN_CONF_NAME "conf/login_athena.conf" #define SQL_CONF_NAME "conf/inter_athena.conf" #define LAN_CONF_NAME "conf/subnet_athena.conf" @@ -18,9 +20,9 @@ struct mmo_account { int passwdenc; int account_id; - int char_id; long login_id1; long login_id2; + int char_id; char lastlogin[24]; int sex; uint8 level; @@ -28,6 +30,7 @@ struct mmo_account { struct mmo_char_server { char name[20]; + int fd; uint32 ip; uint16 port; int users; @@ -35,4 +38,42 @@ struct mmo_char_server { int new_; }; +extern struct Login_Config { + + uint32 login_ip; // the address to bind to + uint16 login_port; // the port to bind to + unsigned int ip_sync_interval; // interval (in minutes) to execute a DNS/IP update (for dynamic IPs) + bool log_login; // whether to log login server actions or not + char date_format[32]; // date format used in messages + bool console; // console input system enabled? + bool new_account_flag; // autoregistration via _M/_F ? + bool case_sensitive; // are logins case sensitive ? + bool use_md5_passwds; // work with password hashes instead of plaintext passwords? + bool login_gm_read; // should the login server handle info about gm accounts? + int min_level_to_connect; // minimum level of player/GM (0: player, 1-99: GM) to connect + bool online_check; // reject incoming players that are already registered as online ? + bool check_client_version; // check the clientversion set in the clientinfo ? + int client_version_to_connect; // the client version needed to connect (if checking is enabled) + + bool ipban; // perform IP blocking (via contents of `ipbanlist`) ? + bool dynamic_pass_failure_ban; // automatic IP blocking due to failed login attemps ? + unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures + unsigned int dynamic_pass_failure_ban_limit; // number of failures needed to trigger the ipban + unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban + bool use_dnsbl; // dns blacklist blocking ? + char dnsbl_servs[1024]; // comma-separated list of dnsbl servers + +} login_config; + +// stores auth information of incoming clients +// used during charserver auth validation process +#define AUTH_FIFO_SIZE 256 +extern struct _auth_fifo { + int account_id; + uint32 login_id1, login_id2; + uint32 ip; + uint8 sex; + bool delflag; +} auth_fifo[AUTH_FIFO_SIZE]; + #endif /* _LOGIN_SQL_H_ */ diff --git a/src/map/clif.h b/src/map/clif.h index ca26a9b67..daca310ef 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -30,7 +30,7 @@ struct guild; // v8 - 2007-05-21aSakexe+ - 0x283 // v9 - 2007-11-06aSakexe+ - 0x78, 0x7c, 0x22c #ifndef PACKETVER - #define PACKETVER 8 + #define PACKETVER 7 #endif // packet DB diff --git a/src/map/script.c b/src/map/script.c index 4e81e752e..bf8b3ea93 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -11610,7 +11610,7 @@ BUILDIN_FUNC(query_sql) num_cols = Sql_NumColumns(mmysql_handle); if( num_vars < num_cols ) { - ShowWarning("script:query_sql: Too many columns, discarting last %u columns.\n", (unsigned int)(num_cols-num_vars)); + ShowWarning("script:query_sql: Too many columns, discarding last %u columns.\n", (unsigned int)(num_cols-num_vars)); script_reportsrc(st); } else if( num_vars > num_cols ) -- cgit v1.2.3-60-g2f50