* 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://svn.code.sf.net/p/rathena/svn/trunk@11826 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
ultramage 2007-11-27 19:38:16 +00:00
parent 4b8cf3c768
commit ea5212c5a8
16 changed files with 701 additions and 1893 deletions

View File

@ -4,6 +4,14 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/11/27 2007/11/27
* removed login/char server_fd[] arrays, added server[].fd instead
* TXT/SQL login server code synchronization [ultramage]
- 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
* Moved basic max HP/SP calculation to before parsing equipment, fixes * Moved basic max HP/SP calculation to before parsing equipment, fixes
negative absolute HP/SP bonuses not working. negative absolute HP/SP bonuses not working.
* Corrected the online_data_cleanup routine setting offline characters that * Corrected the online_data_cleanup routine setting offline characters that

View File

@ -34,8 +34,8 @@ stdout_with_ansisequence: no
//Example: "console_silent: 7" Hides information, status and notice messages (1+2+4) //Example: "console_silent: 7" Hides information, status and notice messages (1+2+4)
console_silent: 0 console_silent: 0
// Whether remote administration is enabled or disabled (1 for enabled, 0 for disabled) // Whether remote administration is enabled or disabled
admin_state: 0 admin_state: no
// Administrative password, used by ladmin (perl software) to connect remotely to server. // Administrative password, used by ladmin (perl software) to connect remotely to server.
// NOTICE: If you enable remote administration, you should change its value for security // NOTICE: If you enable remote administration, you should change its value for security
@ -88,9 +88,6 @@ gm_account_filename: conf/GM_account.txt
// (in seconds; default: 15; value: 0 (disabled), or 2 or more) // (in seconds; default: 15; value: 0 (disabled), or 2 or more)
gm_account_filename_check_timer: 15 gm_account_filename_check_timer: 15
// Log Filename. All operations received by the server are logged in this file.
login_log_filename: log/login.log
// To log the login server? // To log the login server?
// NOTE: The login-sql server needs the login logs to enable dynamic pass failure bans. // NOTE: The login-sql server needs the login logs to enable dynamic pass failure bans.
log_login: yes log_login: yes

View File

@ -57,12 +57,12 @@ int save_log = 1; // show loading/saving messages
char db_path[1024] = "db"; char db_path[1024] = "db";
struct mmo_map_server { struct mmo_map_server {
int fd;
uint32 ip; uint32 ip;
uint16 port; uint16 port;
int users; int users;
unsigned short map[MAX_MAP_PER_SERVER]; unsigned short map[MAX_MAP_PER_SERVER];
} server[MAX_MAP_SERVERS]; } server[MAX_MAP_SERVERS];
int server_fd[MAX_MAP_SERVERS];
int login_fd, char_fd; int login_fd, char_fd;
char userid[24]; char userid[24];
@ -290,7 +290,7 @@ int search_character_online(int aid, int cid)
if(character && if(character &&
character->char_id == cid && character->char_id == cid &&
character->server > -1) character->server > -1)
return server_fd[character->server]; return server[character->server].fd;
return -1; return -1;
} }
static void * create_online_char_data(DBKey key, va_list args) 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) 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", 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); 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; 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) static int char_db_kickoffline(DBKey key, void* data, va_list ap)
{ {
struct online_char_data* character = (struct online_char_data*)data; 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; return 0;
//Kick out any connected characters, and set them offline as appropiate. //Kick out any connected characters, and set them offline as appropiate.
if (character->server > -1) if (character->server > -1)
mapif_disconnectplayer(server_fd[character->server], mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1);
character->account_id, character->char_id, 1);
else if (character->waiting_disconnect == -1) else if (character->waiting_disconnect == -1)
set_char_offline(character->char_id, character->account_id); set_char_offline(character->char_id, character->account_id);
else return 0; else return 0;
@ -1375,7 +1374,7 @@ static int create_online_files_sub(DBKey key, void* data, va_list va)
} }
j = character->server; j = character->server;
if (server_fd[j] < 0) { if (server[j].fd < 0) {
server[j].users = 0; server[j].users = 0;
return -1; return -1;
} }
@ -1670,7 +1669,7 @@ int count_users(void)
users = 0; users = 0;
for(i = 0; i < MAX_MAP_SERVERS; i++) for(i = 0; i < MAX_MAP_SERVERS; i++)
if (server_fd[i] >= 0) if (server[i].fd >= 0)
users += server[i].users; users += server[i].users;
return 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] { // check if character is not online already. [Skotlex]
if (character->server > -1) if (character->server > -1)
{ //Character already online. KICK KICK KICK { //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) if (character->waiting_disconnect == -1)
character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
WFIFOW(fd,0) = 0x81; WFIFOW(fd,0) = 0x81;
@ -1991,7 +1990,7 @@ int parse_fromlogin(int fd)
send_accounts_tologin(-1, gettick(), 0, 0); send_accounts_tologin(-1, gettick(), 0, 0);
// if no map-server already connected, display a message... // 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 ) if( i == MAX_MAP_SERVERS )
ShowStatus("Awaiting maps from map-server.\n"); ShowStatus("Awaiting maps from map-server.\n");
} }
@ -2150,9 +2149,7 @@ int parse_fromlogin(int fd)
else else
{ {
// at least 1 map-server // at least 1 map-server
for(i = 0; i < MAX_MAP_SERVERS; i++) ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd >= 0 );
if (server_fd[i] >= 0)
break;
if (i == MAX_MAP_SERVERS) if (i == MAX_MAP_SERVERS)
char_log("'ladmin': Receiving a message for broadcast, but no map-server is online.\n"); char_log("'ladmin': Receiving a message for broadcast, but no map-server is online.\n");
else { else {
@ -2328,7 +2325,7 @@ int parse_fromlogin(int fd)
{ //Kick out this player. { //Kick out this player.
if (character->server > -1) if (character->server > -1)
{ //Kick it from the map server it is on. { //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) if (character->waiting_disconnect == -1)
character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0); character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0);
} else { //Manual kick from char server. } else { //Manual kick from char server.
@ -2605,9 +2602,7 @@ int parse_frommap(int fd)
int i, j; int i, j;
int id; int id;
for(id = 0; id < MAX_MAP_SERVERS; id++) ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd );
if (server_fd[id] == fd)
break;
if(id == MAX_MAP_SERVERS) if(id == MAX_MAP_SERVERS)
set_eof(fd); set_eof(fd);
if(session[fd]->eof) { if(session[fd]->eof) {
@ -2626,7 +2621,7 @@ int parse_frommap(int fd)
WBUFW(buf,2) = j * 4 + 10; WBUFW(buf,2) = j * 4 + 10;
mapif_sendallwos(fd, buf, WBUFW(buf,2)); 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. online_char_db->foreach(online_char_db,char_db_setoffline,i); //Tag relevant chars as 'in disconnected' server.
} }
do_close(fd); 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 // Transmitting the maps of the other map-servers to the new map-server
for(x = 0; x < MAX_MAP_SERVERS; x++) { 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); WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER);
WFIFOW(fd,0) = 0x2b04; WFIFOW(fd,0) = 0x2b04;
WFIFOL(fd,4) = htonl(server[x].ip); 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", 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); 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->char_id = cid;
character->server = id; character->server = id;
@ -2833,7 +2828,7 @@ int parse_frommap(int fd)
name = RFIFOW(fd,18); name = RFIFOW(fd,18);
map_id = search_mapserver(name, ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. map_id = search_mapserver(name, ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port.
if (map_id >= 0) if (map_id >= 0)
map_fd = server_fd[map_id]; map_fd = server[map_id].fd;
for(i = 0; i < char_num; i++) { for(i = 0; i < char_num; i++) {
if (char_dat[i].status.account_id == RFIFOL(fd,2) && if (char_dat[i].status.account_id == RFIFOL(fd,2) &&
char_dat[i].status.char_id == RFIFOL(fd,14)) 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++) 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) && (ip == (uint32)-1 || server[i].ip == ip)
&& (port == (uint16)-1 || server[i].port == port)) && (port == (uint16)-1 || server[i].port == port))
{ {
@ -3355,7 +3350,7 @@ int parse_char(int fd)
if (i < 0) { if (i < 0) {
unsigned short j; unsigned short j;
//First check that there's actually a map server online. //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) { if (j == MAX_MAP_SERVERS) {
ShowInfo("Connection Closed. No map servers available.\n"); ShowInfo("Connection Closed. No map servers available.\n");
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
@ -3421,10 +3416,10 @@ int parse_char(int fd)
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
//Send NEW auth packet [Kevin] //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); 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)); memset(&server[i], 0, sizeof(struct mmo_map_server));
//Send server closed. //Send server closed.
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
@ -3626,10 +3621,7 @@ int parse_char(int fd)
char* l_pass = RFIFOP(fd,26); char* l_pass = RFIFOP(fd,26);
l_user[23] = '\0'; l_user[23] = '\0';
l_pass[23] = '\0'; l_pass[23] = '\0';
for(i = 0; i < MAX_MAP_SERVERS; i++) { ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 );
if (server_fd[i] <= 0)
break;
}
if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) { if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) {
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9; WFIFOW(fd,0) = 0x2af9;
@ -3641,7 +3633,7 @@ int parse_char(int fd)
WFIFOB(fd,2) = 0; WFIFOB(fd,2) = 0;
WFIFOSET(fd,3); WFIFOSET(fd,3);
server_fd[i] = fd; server[i].fd = fd;
server[i].ip = ntohl(RFIFOL(fd,54)); server[i].ip = ntohl(RFIFOL(fd,54));
server[i].port = ntohs(RFIFOW(fd,58)); server[i].port = ntohs(RFIFOW(fd,58));
server[i].users = 0; server[i].users = 0;
@ -3736,7 +3728,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len)
c = 0; c = 0;
for(i = 0; i < MAX_MAP_SERVERS; i++) { for(i = 0; i < MAX_MAP_SERVERS; i++) {
int fd; int fd;
if ((fd = server_fd[i]) > 0) { if ((fd = server[i].fd) > 0) {
WFIFOHEAD(fd,len); WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len); memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len); WFIFOSET(fd,len);
@ -3755,7 +3747,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
c = 0; c = 0;
for(i = 0; i < MAX_MAP_SERVERS; i++) { for(i = 0; i < MAX_MAP_SERVERS; i++) {
int fd; int fd;
if ((fd = server_fd[i]) > 0 && fd != sfd) { if ((fd = server[i].fd) > 0 && fd != sfd) {
WFIFOHEAD(fd,len); WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len); memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len); WFIFOSET(fd,len);
@ -3772,7 +3764,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
if (fd >= 0) { if (fd >= 0) {
for(i = 0; i < MAX_MAP_SERVERS; i++) { for(i = 0; i < MAX_MAP_SERVERS; i++) {
if (fd == server_fd[i]) { if (fd == server[i].fd) {
WFIFOHEAD(fd,len); WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len); memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len); WFIFOSET(fd,len);
@ -4229,7 +4221,7 @@ int do_init(int argc, char **argv)
for(i = 0; i < MAX_MAP_SERVERS; i++) { for(i = 0; i < MAX_MAP_SERVERS; i++) {
memset(&server[i], 0, sizeof(struct mmo_map_server)); memset(&server[i], 0, sizeof(struct mmo_map_server));
server_fd[i] = -1; server[i].fd = -1;
} }
//Read map indexes //Read map indexes

View File

@ -103,7 +103,7 @@ int inter_homun_fromstr(char *str,struct s_homunculus *p)
p->hskill[i].id = tmp_int[0]; p->hskill[i].id = tmp_int[0];
p->hskill[i].lv = tmp_int[1]; p->hskill[i].lv = tmp_int[1];
} else } 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; next += len;
if (str[next] == ' ') if (str[next] == ' ')
next++; next++;

View File

@ -77,12 +77,12 @@ char login_db_level[32] = "level";
int lowest_gm_level = 1; int lowest_gm_level = 1;
struct mmo_map_server { struct mmo_map_server {
int fd;
uint32 ip; uint32 ip;
uint16 port; uint16 port;
int users; int users;
unsigned short map[MAX_MAP_PER_SERVER]; unsigned short map[MAX_MAP_PER_SERVER];
} server[MAX_MAP_SERVERS]; } server[MAX_MAP_SERVERS];
int server_fd[MAX_MAP_SERVERS];
int login_fd, char_fd; int login_fd, char_fd;
char userid[24]; char userid[24];
@ -239,7 +239,7 @@ void set_char_online(int map_id, int char_id, int account_id)
if (char_id != 99) 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", 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); 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; 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) static int char_db_kickoffline(DBKey key, void* data, va_list ap)
{ {
struct online_char_data* character = (struct online_char_data*)data; 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; return 0;
//Kick out any connected characters, and set them offline as appropiate. //Kick out any connected characters, and set them offline as appropiate.
if (character->server > -1) if (character->server > -1)
mapif_disconnectplayer(server_fd[character->server], mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 1);
character->account_id, character->char_id, 1);
else if (character->waiting_disconnect == -1) else if (character->waiting_disconnect == -1)
set_char_offline(character->char_id, character->account_id); set_char_offline(character->char_id, character->account_id);
else return 0; else return 0;
@ -1423,7 +1422,7 @@ int count_users(void)
if (login_fd > 0 && session[login_fd]){ if (login_fd > 0 && session[login_fd]){
users = 0; users = 0;
for(i = 0; i < MAX_MAP_SERVERS; i++) { for(i = 0; i < MAX_MAP_SERVERS; i++) {
if (server_fd[i] > 0) { if (server[i].fd > 0) {
users += server[i].users; 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] { // check if character is not online already. [Skotlex]
if (character->server > -1) if (character->server > -1)
{ //Character already online. KICK KICK KICK { //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) if (character->waiting_disconnect == -1)
character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); character->waiting_disconnect = add_timer(gettick()+20000, chardb_waiting_disconnect, character->account_id, 0);
WFIFOW(fd,0) = 0x81; WFIFOW(fd,0) = 0x81;
@ -1660,7 +1659,7 @@ int parse_fromlogin(int fd)
send_accounts_tologin(-1, gettick(), 0, 0); send_accounts_tologin(-1, gettick(), 0, 0);
// if no map-server already connected, display a message... // 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 ) if( i == MAX_MAP_SERVERS )
ShowStatus("Awaiting maps from map-server.\n"); ShowStatus("Awaiting maps from map-server.\n");
} }
@ -1892,7 +1891,7 @@ int parse_fromlogin(int fd)
{ //Kick out this player. { //Kick out this player.
if( character->server != -1 ) if( character->server != -1 )
{ //Kick it from the map server it is on. { //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) if (character->waiting_disconnect == -1)
character->waiting_disconnect = add_timer(gettick()+15000, chardb_waiting_disconnect, character->account_id, 0); 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; return 0;
} }
for(id = 0; id < MAX_MAP_SERVERS; id++) ARR_FIND( 0, MAX_MAP_SERVERS, id, server[id].fd == fd );
if (server_fd[id] == fd)
break;
if(id == MAX_MAP_SERVERS) if(id == MAX_MAP_SERVERS)
set_eof(fd); set_eof(fd);
if(session[fd]->eof) { if(session[fd]->eof) {
@ -2146,9 +2143,9 @@ int parse_frommap(int fd)
mapif_sendallwos(fd, buf, WBUFW(buf,2)); mapif_sendallwos(fd, buf, WBUFW(buf,2));
} }
memset(&server[id], 0, sizeof(struct mmo_map_server)); 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); 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. online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server.
} }
do_close(fd); 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 // Transmitting the maps of the other map-servers to the new map-server
for(x = 0; x < MAX_MAP_SERVERS; x++) { 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); WFIFOHEAD(fd,10 +4*MAX_MAP_PER_SERVER);
WFIFOW(fd,0) = 0x2b04; WFIFOW(fd,0) = 0x2b04;
WFIFOL(fd,4) = htonl(server[x].ip); 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", 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); 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->server = id;
character->char_id = cid; 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. 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) 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 should just had been saved before this packet, so this should be safe. [Skotlex]
char_data = uidb_get(char_db_,RFIFOL(fd,14)); char_data = uidb_get(char_db_,RFIFOL(fd,14));
if (char_data == NULL) 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++) 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) && (ip == (uint32)-1 || server[i].ip == ip)
&& (port == (uint16)-1 || server[i].port == port)) && (port == (uint16)-1 || server[i].port == port))
{ {
@ -2930,7 +2927,7 @@ int parse_char(int fd)
if (i < 0) { if (i < 0) {
unsigned short j; unsigned short j;
//First check that there's actually a map server online. //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) { if (j == MAX_MAP_SERVERS) {
ShowInfo("Connection Closed. No map servers available.\n"); ShowInfo("Connection Closed. No map servers available.\n");
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
@ -2994,10 +2991,10 @@ int parse_char(int fd)
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
//Send NEW auth packet [Kevin] //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); 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)); memset(&server[i], 0, sizeof(struct mmo_map_server));
//Send server closed. //Send server closed.
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
@ -3174,10 +3171,7 @@ int parse_char(int fd)
char* l_pass = RFIFOP(fd,26); char* l_pass = RFIFOP(fd,26);
l_user[23] = '\0'; l_user[23] = '\0';
l_pass[23] = '\0'; l_pass[23] = '\0';
for(i = 0; i < MAX_MAP_SERVERS; i++) { ARR_FIND( 0, MAX_MAP_SERVERS, i, server[i].fd <= 0 );
if (server_fd[i] <= 0)
break;
}
if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) { if (i == MAX_MAP_SERVERS || strcmp(l_user, userid) || strcmp(l_pass, passwd)) {
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9; WFIFOW(fd,0) = 0x2af9;
@ -3189,7 +3183,7 @@ int parse_char(int fd)
WFIFOB(fd,2) = 0; WFIFOB(fd,2) = 0;
WFIFOSET(fd,3); WFIFOSET(fd,3);
server_fd[i] = fd; server[i].fd = fd;
server[i].ip = ntohl(RFIFOL(fd,54)); server[i].ip = ntohl(RFIFOL(fd,54));
server[i].port = ntohs(RFIFOW(fd,58)); server[i].port = ntohs(RFIFOW(fd,58));
server[i].users = 0; server[i].users = 0;
@ -3284,7 +3278,7 @@ int mapif_sendall(unsigned char *buf, unsigned int len)
c = 0; c = 0;
for(i = 0; i < MAX_MAP_SERVERS; i++) { for(i = 0; i < MAX_MAP_SERVERS; i++) {
int fd; int fd;
if ((fd = server_fd[i]) > 0) { if ((fd = server[i].fd) > 0) {
WFIFOHEAD(fd,len); WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len); memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len); WFIFOSET(fd,len);
@ -3302,7 +3296,7 @@ int mapif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
c = 0; c = 0;
for(i = 0; i < MAX_MAP_SERVERS; i++) { for(i = 0; i < MAX_MAP_SERVERS; i++) {
int fd; int fd;
if ((fd = server_fd[i]) > 0 && fd != sfd) { if ((fd = server[i].fd) > 0 && fd != sfd) {
WFIFOHEAD(fd,len); WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len); memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len); WFIFOSET(fd,len);
@ -3318,7 +3312,7 @@ int mapif_send(int fd, unsigned char *buf, unsigned int len)
int i; int i;
if (fd >= 0) { 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 ) if( i < MAX_MAP_SERVERS )
{ {
WFIFOHEAD(fd,len); WFIFOHEAD(fd,len);
@ -3835,7 +3829,7 @@ int do_init(int argc, char **argv)
for(i = 0; i < MAX_MAP_SERVERS; i++) { for(i = 0; i < MAX_MAP_SERVERS; i++) {
memset(&server[i], 0, sizeof(struct mmo_map_server)); memset(&server[i], 0, sizeof(struct mmo_map_server));
server_fd[i] = -1; server[i].fd = -1;
} }
//Read map indexes //Read map indexes

View File

@ -4087,37 +4087,37 @@ int parse_fromlogin(int fd)
if (defaultlanguage == 'F') if (defaultlanguage == 'F')
ShowMessage(" Statut: 0 [Compte Ok]\n"); ShowMessage(" Statut: 0 [Compte Ok]\n");
else else
ShowMessage(" Statut: 0 [Account OK]\n"); ShowMessage(" State: 0 [Account OK]\n");
break; break;
case 1: case 1:
ShowMessage(" Statut: 1 [Unregistered ID]\n"); ShowMessage(" Statut: 1 [Unregistered ID]\n");
break; break;
case 2: case 2:
ShowMessage(" Statut: 2 [Incorrect Password]\n"); ShowMessage(" State: 2 [Incorrect Password]\n");
break; break;
case 3: case 3:
ShowMessage(" Statut: 3 [This ID is expired]\n"); ShowMessage(" Statut: 3 [This ID is expired]\n");
break; break;
case 4: case 4:
ShowMessage(" Statut: 4 [Rejected from Server]\n"); ShowMessage(" State: 4 [Rejected from Server]\n");
break; break;
case 5: case 5:
ShowMessage(" Statut: 5 [You have been blocked by the GM Team]\n"); ShowMessage(" Statut: 5 [You have been blocked by the GM Team]\n");
break; break;
case 6: 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; break;
case 7: case 7:
ShowMessage(" Statut: 7 [You are Prohibited to log in until %s]\n", error_message); ShowMessage(" Statut: 7 [You are Prohibited to log in until %s]\n", error_message);
break; break;
case 8: 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; break;
case 9: case 9:
ShowMessage(" Statut: 9 [No MSG]\n"); ShowMessage(" Statut: 9 [No MSG]\n");
break; break;
default: // 100 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; break;
} }
if (defaultlanguage == 'F') { if (defaultlanguage == 'F') {
@ -4232,6 +4232,18 @@ int Connect_login_server(void)
return 0; 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 // Reading general configuration file
//----------------------------------- //-----------------------------------
@ -4380,6 +4392,10 @@ int do_init(int argc, char **argv)
Connect_login_server(); 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, // minimalist core doesn't have sockets parsing,
// so we have to do this ourselves // so we have to do this ourselves
while (runflag) { while (runflag) {

View File

@ -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/grfio.h ../common/mapindex.h \
../common/ers.h ../common/md5calc.h ../common/ers.h ../common/md5calc.h
LOGIN_OBJ = obj/login.o LOGIN_OBJ = obj/login.o obj/admin.o
LOGIN_H = login.h LOGIN_H = login.h
@SET_MAKE@ @SET_MAKE@

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
#ifndef _LOGIN_H_ #ifndef _LOGIN_H_
#define _LOGIN_H_ #define _LOGIN_H_
#include "../common/mmo.h" #include "../common/mmo.h" // NAME_LENGTH
#define LOGIN_CONF_NAME "conf/login_athena.conf" #define LOGIN_CONF_NAME "conf/login_athena.conf"
#define LAN_CONF_NAME "conf/subnet_athena.conf" #define LAN_CONF_NAME "conf/subnet_athena.conf"
@ -24,10 +24,12 @@ struct mmo_account {
long char_id; long char_id;
char lastlogin[24]; char lastlogin[24];
char sex; char sex;
//uint8 level;
}; };
struct mmo_char_server { struct mmo_char_server {
char name[20]; char name[20];
int fd;
uint32 ip; uint32 ip;
uint16 port; uint16 port;
uint16 users; // user count on this server uint16 users; // user count on this server
@ -35,4 +37,62 @@ struct mmo_char_server {
uint16 new_; // allows creating new chars? 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_ */ #endif /* _LOGIN_H_ */

View File

@ -20,36 +20,10 @@
#include <string.h> #include <string.h>
#include <sys/stat.h> // for stat/lstat/fstat #include <sys/stat.h> // for stat/lstat/fstat
struct Login_Config { struct Login_Config 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;
int login_fd; // login server socket int login_fd; // login server socket
#define MAX_SERVERS 30 #define MAX_SERVERS 30
int server_fd[MAX_SERVERS]; // char server sockets
struct mmo_char_server server[MAX_SERVERS]; // char server data struct mmo_char_server server[MAX_SERVERS]; // char server data
// Advanced subnet check [LuzZza] // Advanced subnet check [LuzZza]
@ -98,25 +72,22 @@ struct login_session_data {
char md5key[20]; char md5key[20];
}; };
#define AUTH_FIFO_SIZE 256 // auth information of incoming clients
struct _auth_fifo { struct _auth_fifo auth_fifo[AUTH_FIFO_SIZE];
int account_id;
uint32 login_id1, login_id2;
uint32 ip;
uint8 sex;
bool delflag;
} auth_fifo[AUTH_FIFO_SIZE];
int auth_fifo_pos = 0; int auth_fifo_pos = 0;
//-----------------------------------------------------
// Online User Database [Wizputer]
//-----------------------------------------------------
struct online_login_data { struct online_login_data {
int account_id; int account_id;
int waiting_disconnect; int waiting_disconnect;
int char_server; int char_server;
}; };
//-----------------------------------------------------
static DBMap* online_db; // int account_id -> struct online_login_data* 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) 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; 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) void add_online_user(int char_server, int account_id)
{ {
struct online_login_data* p; 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; 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]; int i, c;
ShowInfo("IP Sync in progress...\n");
WBUFW(buf,0) = 0x2735; for( i = 0, c = 0; i < MAX_SERVERS; ++i )
charif_sendallwos(-1, buf, 2); {
return 0; 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 ) for( i = 0; i < MAX_SERVERS; ++i )
{ {
fd = server_fd[i]; fd = server[i].fd;
if( session_isValid(fd) ) if( session_isValid(fd) )
{// Clean only data related to servers we are connected to. [Skotlex] {// 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) ) 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); do_close(login_fd);
} }
//-----------------------------------------------------
//-------------------------------------------------------------------- // periodic ip address synchronization
// Packet send to all char-servers, except one (wos: without our self) //-----------------------------------------------------
//-------------------------------------------------------------------- static int sync_ip_addresses(int tid, unsigned int tick, int id, int data)
int charif_sendallwos(int sfd, uint8* buf, size_t len)
{ {
int i, c; uint8 buf[2];
ShowInfo("IP Sync in progress...\n");
for( i = 0, c = 0; i < MAX_SERVERS; ++i ) WBUFW(buf,0) = 0x2735;
{ charif_sendallwos(-1, buf, 2);
int fd = server_fd[i]; return 0;
if( session_isValid(fd) && fd != sfd )
{
WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len);
++c;
}
}
return c;
} }
//----------------------------------------------------- //-----------------------------------------------------
// encrypted/unencrypted password check // encrypted/unencrypted password check
//----------------------------------------------------- //-----------------------------------------------------
@ -645,7 +610,7 @@ int parse_fromchar(int fd)
char ip[16]; char ip[16];
ip2str(ipl, ip); 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 ) if( id == MAX_SERVERS )
{// not a char server {// not a char server
set_eof(fd); set_eof(fd);
@ -656,7 +621,7 @@ int parse_fromchar(int fd)
if( session[fd]->eof ) if( session[fd]->eof )
{ {
ShowStatus("Char-server '%s' has disconnected.\n", server[id].name); 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)); 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. 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) ) 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 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( 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) ) 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; return 0;
{ {
int account_id = RFIFOL(fd,2); int account_id = RFIFOL(fd,2);
for( i = 0; i < AUTH_FIFO_SIZE; ++i ) ARR_FIND( 0, AUTH_FIFO_SIZE, i,
{ auth_fifo[i].account_id == RFIFOL(fd,2) &&
if( auth_fifo[i].account_id == RFIFOL(fd,2) && auth_fifo[i].login_id1 == RFIFOL(fd,6) &&
auth_fifo[i].login_id1 == RFIFOL(fd,6) && auth_fifo[i].login_id2 == RFIFOL(fd,10) &&
auth_fifo[i].login_id2 == RFIFOL(fd,10) && auth_fifo[i].sex == RFIFOB(fd,14) &&
auth_fifo[i].sex == RFIFOB(fd,14) && auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) &&
auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) && !auth_fifo[i].delflag );
!auth_fifo[i].delflag)
{
auth_fifo[i].delflag = 1;
break;
}
}
if( i != AUTH_FIFO_SIZE && account_id > 0 ) if( i < AUTH_FIFO_SIZE )
auth_fifo[i].delflag = 1;
if( i < AUTH_FIFO_SIZE && account_id > 0 )
{// send ack {// send ack
uint32 connect_until_time; uint32 connect_until_time;
char email[40]; char email[40];
@ -737,7 +700,8 @@ int parse_fromchar(int fd)
WFIFOSET(fd,51); WFIFOSET(fd,51);
} }
else 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); WFIFOHEAD(fd,51);
WFIFOW(fd,0) = 0x2713; WFIFOW(fd,0) = 0x2713;
WFIFOL(fd,2) = account_id; WFIFOL(fd,2) = account_id;
@ -752,7 +716,7 @@ int parse_fromchar(int fd)
break; break;
case 0x2714: case 0x2714:
if (RFIFOREST(fd) < 6) if( RFIFOREST(fd) < 6 )
return 0; return 0;
// how many users on world? (update) // how many users on world? (update)
@ -906,9 +870,8 @@ int parse_fromchar(int fd)
if (RFIFOREST(fd) < 10) if (RFIFOREST(fd) < 10)
return 0; return 0;
{ {
int account_id, state; int account_id = RFIFOL(fd,2);
account_id = RFIFOL(fd,2); int state = RFIFOL(fd,6);
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) ) 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); Sql_ShowDebug(sql_handle);
else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
@ -990,7 +953,7 @@ int parse_fromchar(int fd)
break; break;
case 0x2727: // Change of sex (sex is reversed) case 0x2727: // Change of sex (sex is reversed)
if (RFIFOREST(fd) < 6) if( RFIFOREST(fd) < 6 )
return 0; return 0;
{ {
int account_id; int account_id;
@ -1099,14 +1062,14 @@ int parse_fromchar(int fd)
} }
case 0x272b: // Set account_id to online [Wizputer] case 0x272b: // Set account_id to online [Wizputer]
if (RFIFOREST(fd) < 6) if( RFIFOREST(fd) < 6 )
return 0; return 0;
add_online_user(id, RFIFOL(fd,2)); add_online_user(id, RFIFOL(fd,2));
RFIFOSKIP(fd,6); RFIFOSKIP(fd,6);
break; break;
case 0x272c: // Set account_id to offline [Wizputer] case 0x272c: // Set account_id to offline [Wizputer]
if (RFIFOREST(fd) < 6) if( RFIFOREST(fd) < 6 )
return 0; return 0;
remove_online_user(RFIFOL(fd,2)); remove_online_user(RFIFOL(fd,2));
RFIFOSKIP(fd,6); RFIFOSKIP(fd,6);
@ -1179,7 +1142,7 @@ int parse_fromchar(int fd)
break; break;
case 0x2736: // WAN IP update from char-server case 0x2736: // WAN IP update from char-server
if (RFIFOREST(fd) < 6) if( RFIFOREST(fd) < 6 )
return 0; return 0;
server[id].ip = ntohl(RFIFOL(fd,2)); server[id].ip = ntohl(RFIFOL(fd,2));
ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip)); 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; uint32 ipl = session[fd]->client_addr;
char ip[16]; char ip[16];
ip2str(ipl, ip);
if( session[fd]->eof ) if( session[fd]->eof )
{ {
do_close(fd); do_close(fd);
return 0; return 0;
} }
ip2str(ipl, ip);
while( RFIFOREST(fd) >= 2 ) while( RFIFOREST(fd) >= 2 )
{ {
uint16 command = RFIFOW(fd,0); 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 0x0277: // New login packet (kRO 2006-04-24aSakexe langtype 0)
case 0x02b0: // New login packet (kRO 2007-05-14aSakexe 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 // Perform ip-ban check
if( login_config.ipban && login_ip_ban_check(ipl) ) 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); WFIFOHEAD(fd,23);
WFIFOW(fd,0) = 0x6a; WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = 3; // 3 = Rejected from Server WFIFOB(fd,2) = 3; // 3 = Rejected from Server
@ -1326,6 +1290,7 @@ int parse_login(int fd)
{ // auth success { // auth success
if( login_config.min_level_to_connect > account.level ) 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); WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x81; WFIFOW(fd,0) = 0x81;
WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOB(fd,2) = 1; // 01 = Server closed
@ -1333,32 +1298,24 @@ int parse_login(int fd)
} }
else 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) ) server_num = 0;
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);
for( i = 0; i < MAX_SERVERS; ++i ) for( i = 0; i < MAX_SERVERS; ++i )
{ if( session_isValid(server[i].fd) )
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_;
server_num++; server_num++;
}
} if( server_num > 0 )
if (server_num > 0) { // if at least 1 char-server {// 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,0) = 0x69;
WFIFOW(fd,2) = 47+32*server_num; WFIFOW(fd,2) = 47+32*server_num;
WFIFOL(fd,4) = account.login_id1; WFIFOL(fd,4) = account.login_id1;
@ -1366,8 +1323,24 @@ int parse_login(int fd)
WFIFOL(fd,12) = account.login_id2; WFIFOL(fd,12) = account.login_id2;
WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used) 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) //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; 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); WFIFOSET(fd,47+32*server_num);
if (auth_fifo_pos >= AUTH_FIFO_SIZE) if (auth_fifo_pos >= AUTH_FIFO_SIZE)
auth_fifo_pos = 0; auth_fifo_pos = 0;
auth_fifo[auth_fifo_pos].account_id = account.account_id; 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].delflag = 0;
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr; auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
auth_fifo_pos++; 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; WFIFOW(fd,0) = 0x81;
WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOB(fd,2) = 1; // 01 = Server closed
WFIFOSET(fd,3); WFIFOSET(fd,3);
@ -1445,7 +1422,9 @@ int parse_login(int fd)
WFIFOHEAD(fd,23); WFIFOHEAD(fd,23);
WFIFOW(fd,0) = 0x6a; WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = (uint8)result; 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 {// 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) ) 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); 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)); strftime((char*)WFIFOP(fd,3), 20, login_config.date_format, localtime(&ban_until_time));
} }
} }
else
memset(WFIFOP(fd,3), '\0', 20);
WFIFOSET(fd,23); WFIFOSET(fd,23);
} }
@ -1526,7 +1503,7 @@ int parse_login(int fd)
Sql_ShowDebug(sql_handle); Sql_ShowDebug(sql_handle);
result = mmo_auth(&account, fd); 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); ShowStatus("Connection of the char-server '%s' accepted.\n", esc_server_name);
memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); 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].users = 0;
server[account.account_id].maintenance = RFIFOW(fd,82); server[account.account_id].maintenance = RFIFOW(fd,82);
server[account.account_id].new_ = RFIFOW(fd,84); server[account.account_id].new_ = RFIFOW(fd,84);
server_fd[account.account_id] = fd; server[account.account_id].fd = fd;
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2711; WFIFOW(fd,0) = 0x2711;
@ -1560,14 +1537,12 @@ int parse_login(int fd)
WFIFOB(fd,2) = 3; WFIFOB(fd,2) = 3;
WFIFOSET(fd,3); WFIFOSET(fd,3);
} }
}
RFIFOSKIP(fd,86); RFIFOSKIP(fd,86);
return 0; return 0;
}
case 0x7530: // Server version information request case 0x7530: // Server version information request
{ ShowStatus("Sending server version information to ip: %s\n", ip);
ShowInfo ("Athena version check...\n");
WFIFOHEAD(fd,10); WFIFOHEAD(fd,10);
WFIFOW(fd,0) = 0x7531; WFIFOW(fd,0) = 0x7531;
WFIFOB(fd,2) = ATHENA_MAJOR_VERSION; WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
@ -1580,7 +1555,6 @@ int parse_login(int fd)
WFIFOSET(fd,10); WFIFOSET(fd,10);
RFIFOSKIP(fd,2); RFIFOSKIP(fd,2);
}
break; break;
case 0x7532: // Request to end connection case 0x7532: // Request to end connection
@ -1589,7 +1563,7 @@ int parse_login(int fd)
break; break;
default: 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); set_eof(fd);
return 0; return 0;
} }
@ -1618,7 +1592,7 @@ int parse_console(char* buf)
strcmpi("end", command) == 0 ) strcmpi("end", command) == 0 )
runflag = 0; runflag = 0;
else else
if( strcmpi("alive", command) == 0 || if( strcmpi("alive", command) == 0 ||
strcmpi("status", command) == 0 ) strcmpi("status", command) == 0 )
ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n"); ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
else else
@ -1931,7 +1905,7 @@ int do_init(int argc, char** argv)
auth_fifo[i].delflag = 1; auth_fifo[i].delflag = 1;
for( i = 0; i < MAX_SERVERS; i++ ) for( i = 0; i < MAX_SERVERS; i++ )
server_fd[i] = -1; server[i].fd = -1;
// Online user database init // Online user database init
online_db = idb_alloc(DB_OPT_RELEASE_DATA); online_db = idb_alloc(DB_OPT_RELEASE_DATA);

View File

@ -4,6 +4,8 @@
#ifndef _LOGIN_SQL_H_ #ifndef _LOGIN_SQL_H_
#define _LOGIN_SQL_H_ #define _LOGIN_SQL_H_
#include "../common/mmo.h" // NAME_LENGTH
#define LOGIN_CONF_NAME "conf/login_athena.conf" #define LOGIN_CONF_NAME "conf/login_athena.conf"
#define SQL_CONF_NAME "conf/inter_athena.conf" #define SQL_CONF_NAME "conf/inter_athena.conf"
#define LAN_CONF_NAME "conf/subnet_athena.conf" #define LAN_CONF_NAME "conf/subnet_athena.conf"
@ -18,9 +20,9 @@ struct mmo_account {
int passwdenc; int passwdenc;
int account_id; int account_id;
int char_id;
long login_id1; long login_id1;
long login_id2; long login_id2;
int char_id;
char lastlogin[24]; char lastlogin[24];
int sex; int sex;
uint8 level; uint8 level;
@ -28,6 +30,7 @@ struct mmo_account {
struct mmo_char_server { struct mmo_char_server {
char name[20]; char name[20];
int fd;
uint32 ip; uint32 ip;
uint16 port; uint16 port;
int users; int users;
@ -35,4 +38,42 @@ struct mmo_char_server {
int new_; 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_ */ #endif /* _LOGIN_SQL_H_ */

View File

@ -30,7 +30,7 @@ struct guild;
// v8 - 2007-05-21aSakexe+ - 0x283 // v8 - 2007-05-21aSakexe+ - 0x283
// v9 - 2007-11-06aSakexe+ - 0x78, 0x7c, 0x22c // v9 - 2007-11-06aSakexe+ - 0x78, 0x7c, 0x22c
#ifndef PACKETVER #ifndef PACKETVER
#define PACKETVER 8 #define PACKETVER 7
#endif #endif
// packet DB // packet DB

View File

@ -11610,7 +11610,7 @@ BUILDIN_FUNC(query_sql)
num_cols = Sql_NumColumns(mmysql_handle); num_cols = Sql_NumColumns(mmysql_handle);
if( num_vars < num_cols ) 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); script_reportsrc(st);
} }
else if( num_vars > num_cols ) else if( num_vars > num_cols )

View File

@ -187,6 +187,10 @@ SOURCE=..\src\common\version.h
# PROP Default_Filter "" # PROP Default_Filter ""
# Begin Source File # Begin Source File
SOURCE=..\src\login\admin.c
# End Source File
# Begin Source File
SOURCE=..\src\login\login.c SOURCE=..\src\login\login.c
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@ -147,6 +147,9 @@
<Filter <Filter
Name="login_txt" Name="login_txt"
Filter=""> Filter="">
<File
RelativePath="..\src\login\admin.c">
</File>
<File <File
RelativePath="..\src\login\login.c"> RelativePath="..\src\login\login.c">
</File> </File>

View File

@ -203,6 +203,10 @@
<Filter <Filter
Name="login_txt" Name="login_txt"
> >
<File
RelativePath="..\src\login\admin.c"
>
</File>
<File <File
RelativePath="..\src\login\login.c" RelativePath="..\src\login\login.c"
> >