* Made a crazy attempt to at least partially synchronize login&char code

* Major edit to the way the servers handle ip addresses, making them obey the "host byte order inside, network byte order outside" rule
- hopefully covered all entry- and exit-points for IP address data
- discovered several places where Gravity's client breaks the convention, will need to come up with a suitable countermeasure for that
- other than that, the code should be portable, except for printing and ipban mask testing (those still assume a specific byte order)
- tested both txt and sql in all usual situations; tested single- and multi-server setups, all seems to work (but watch out for hidden bugs!)

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@10162 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
ultramage 2007-04-05 18:49:57 +00:00
parent dd818415a1
commit 8dc1b77f03
19 changed files with 1243 additions and 1391 deletions

View File

@ -3,6 +3,17 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/04/06
* Made a crazy attempt to at least partially synchronize login&char code
* Major edit to the way the servers handle ip addresses, making them obey
the "host byte order inside, network byte order outside" rule [ultramage]
- hopefully covered all entry- and exit-points for IP address data
- discovered several places where Gravity's client breaks the convention,
will need to come up with a suitable countermeasure for that
- other than that, the code should be portable, except for printing and
ipban mask testing (those still assume a specific byte order)
- tested both txt and sql in all usual situations; tested single- and
multi-server setups, all seems to work (but watch out for hidden bugs!)
2007/04/05
* Cleaned @whogm. It will display the name of all gms online. If their GM
level is above your own, it will only display their name, otherwise level,

View File

@ -44,8 +44,8 @@
#ifndef TXT_SQL_CONVERT
struct mmo_map_server{
long ip;
short port;
uint32 ip;
uint16 port;
int users;
unsigned short map[MAX_MAP_PER_SERVER];
} server[MAX_MAP_SERVERS];
@ -57,13 +57,13 @@ char passwd[24];
char server_name[20];
char wisp_server_name[NAME_LENGTH] = "Server";
char login_ip_str[128];
in_addr_t login_ip;
int login_port = 6900;
uint32 login_ip;
uint16 login_port = 6900;
char char_ip_str[128];
in_addr_t char_ip;
uint32 char_ip;
char bind_ip_str[128];
in_addr_t bind_ip;
int char_port = 6121;
uint32 bind_ip;
uint16 char_port = 6121;
int char_maintenance;
int char_new;
int char_new_display;
@ -80,10 +80,10 @@ char db_path[1024]="db";
// Advanced subnet check [LuzZza]
struct _subnet {
long subnet;
long mask;
long char_ip;
long map_ip;
uint32 subnet;
uint32 mask;
uint32 char_ip;
uint32 map_ip;
} subnet[16];
int subnet_count = 0;
@ -106,7 +106,10 @@ struct char_session_data{
#define AUTH_FIFO_SIZE 256
struct {
int account_id, char_id, login_id1, login_id2, ip, char_pos, delflag, sex;
int account_id, char_id, login_id1, login_id2;
uint32 ip;
int delflag;
int sex;
time_t connect_until_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
} auth_fifo[AUTH_FIFO_SIZE];
int auth_fifo_pos = 0;
@ -137,7 +140,7 @@ struct fame_list chemist_fame_list[MAX_FAME_LIST];
struct fame_list taekwon_fame_list[MAX_FAME_LIST];
// Initial position (it's possible to set it in conf file)
struct point start_point = { 0, 53, 111};
struct point start_point = { 0, 53, 111 };
struct gm_account *gm_account = NULL;
int GM_num = 0;
@ -2004,7 +2007,7 @@ int parse_tologin(int fd) {
sd = (struct char_session_data*)session[fd]->session_data;
while(RFIFOREST(fd) >= 2 && !session[fd]->eof) {
while(RFIFOREST(fd) >= 2) {
// printf("parse_tologin: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
switch(RFIFOW(fd,0)) {
@ -2105,9 +2108,8 @@ int parse_tologin(int fd) {
auth_fifo[i].login_id1 = RFIFOL(fd,6);
auth_fifo[i].login_id2 = RFIFOL(fd,10);
auth_fifo[i].delflag = 2; // 0: auth_fifo canceled/void, 2: auth_fifo received from login/map server in memory, 1: connection authentified
auth_fifo[i].char_pos = 0;
auth_fifo[i].connect_until_time = 0; // unlimited/unknown time by default (not display in map-server)
auth_fifo[i].ip = RFIFOL(fd,14);
auth_fifo[i].ip = ntohl(RFIFOL(fd,14));
RFIFOSKIP(fd,18);
break;
@ -2472,7 +2474,7 @@ int parse_tologin(int fd) {
case 0x2735:
{
unsigned char buf[2];
in_addr_t new_ip = 0;
uint32 new_ip = 0;
RFIFOSKIP(fd,2);
WBUFW(buf,0) = 0x2b1e;
@ -2487,9 +2489,9 @@ int parse_tologin(int fd) {
{ //Update ip.
WFIFOHEAD(fd,6);
char_ip = new_ip;
ShowInfo("Updating IP for [%s].\n",char_ip_str);
ShowInfo("Updating IP for [%s].\n", char_ip_str);
WFIFOW(fd,0) = 0x2736;
WFIFOL(fd,2) = char_ip;
WFIFOL(fd,2) = htonl(char_ip);
WFIFOSET(fd,6);
}
break;
@ -2693,9 +2695,10 @@ void char_update_fame_list(int type, int index, int fame)
mapif_sendall(buf, 8);
}
int search_mapserver(unsigned short map, long ip, short port);
int search_mapserver(unsigned short map, uint32 ip, uint16 port);
int parse_frommap(int fd) {
int parse_frommap(int fd)
{
int i, j;
int id;
RFIFOHEAD(fd);
@ -2711,8 +2714,8 @@ int parse_frommap(int fd) {
ShowStatus("Map-server %d has disconnected.\n", id);
//Notify other map servers that this one is gone. [Skotlex]
WBUFW(buf,0) = 0x2b20;
WBUFL(buf,4) = server[id].ip;
WBUFW(buf,8) = server[id].port;
WBUFL(buf,4) = htonl(server[id].ip);
WBUFW(buf,8) = htons(server[id].port);
j = 0;
for(i = 0; i < MAX_MAP_PER_SERVER; i++)
if (server[id].map[i])
@ -2734,15 +2737,13 @@ int parse_frommap(int fd) {
switch(RFIFOW(fd,0)) {
// map-server alive packet
case 0x2718:
case 0x2718: // map-server alive packet
if (RFIFOREST(fd) < 2)
return 0;
RFIFOSKIP(fd,2);
break;
// request from map-server to reload GM accounts. Transmission to login-server (by Yor)
case 0x2af7:
case 0x2af7: // request from map-server to reload GM accounts. Transmission to login-server
if (login_fd > 0) { // don't send request if no login-server
WFIFOHEAD(login_fd, 2);
WFIFOW(login_fd,0) = 0x2709;
@ -2751,46 +2752,46 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd,2);
break;
// Receiving map names list from the map-server
case 0x2afa:
case 0x2afa: // Receiving map names list from the map-server
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
memset(server[id].map, 0, sizeof(server[id].map));
j = 0;
for(i = 4; i < RFIFOW(fd,2); i += 4) {
server[id].map[j] = RFIFOW(fd,i);
j++;
}
{
unsigned char *p = (unsigned char *)&server[id].ip;
ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
id, j, p[0], p[1], p[2], p[3], server[id].port);
id, j, CONVIP(server[id].ip), server[id].port);
ShowStatus("Map-server %d loading complete.\n", id);
char_log("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d. Map-server %d loading complete." RETCODE,
id, j, p[0], p[1], p[2], p[3], server[id].port, id);
id, j, CONVIP(server[id].ip), server[id].port, id);
if (max_account_id != DEFAULT_MAX_ACCOUNT_ID || max_char_id != DEFAULT_MAX_CHAR_ID)
mapif_send_maxid(max_account_id, max_char_id); //Send the current max ids to the server to keep in sync [Skotlex]
}
WFIFOHEAD(fd, 3 + NAME_LENGTH);
WFIFOW(fd,0) = 0x2afb;
WFIFOB(fd,2) = 0;
memcpy(WFIFOP(fd,3), wisp_server_name, NAME_LENGTH); // name for wisp to player
WFIFOSET(fd,3+NAME_LENGTH);
//WFIFOSET(fd,27);
char_send_fame_list(fd); //Send fame list.
{
unsigned char buf[16384];
int x;
if (j == 0) {
ShowWarning("Map-Server %d have NO map.\n", id);
char_log("WARNING: Map-Server %d have NO map." RETCODE, id);
// Transmitting maps information to the other map-servers
ShowWarning("Map-server %d has NO maps.\n", id);
char_log("WARNING: Map-server %d has NO maps." RETCODE, id);
} else {
// Transmitting maps information to the other map-servers
WBUFW(buf,0) = 0x2b04;
WBUFW(buf,2) = j * 4 + 10;
WBUFL(buf,4) = server[id].ip;
WBUFW(buf,8) = server[id].port;
WBUFL(buf,4) = htonl(server[id].ip);
WBUFW(buf,8) = htons(server[id].port);
memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4);
mapif_sendallwos(fd, buf, WBUFW(buf,2));
}
@ -2798,8 +2799,8 @@ int parse_frommap(int fd) {
for(x = 0; x < MAX_MAP_SERVERS; x++) {
if (server_fd[x] >= 0 && x != id) {
WFIFOW(fd,0) = 0x2b04;
WFIFOL(fd,4) = server[x].ip;
WFIFOW(fd,8) = server[x].port;
WFIFOL(fd,4) = htonl(server[x].ip);
WFIFOW(fd,8) = htons(server[x].port);
j = 0;
for(i = 0; i < MAX_MAP_PER_SERVER; i++)
if (server[x].map[i])
@ -2814,8 +2815,7 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd,RFIFOW(fd,2));
break;
//Packet command is now used for sc_data request. [Skotlex]
case 0x2afc:
case 0x2afc: //Packet command is now used for sc_data request. [Skotlex]
if (RFIFOREST(fd) < 10)
return 0;
{
@ -2844,8 +2844,7 @@ int parse_frommap(int fd) {
break;
}
//set MAP user count
case 0x2afe:
case 0x2afe: //set MAP user count
if (RFIFOREST(fd) < 4)
return 0;
if (RFIFOW(fd,2) != server[id].users) {
@ -2854,8 +2853,8 @@ int parse_frommap(int fd) {
}
RFIFOSKIP(fd, 4);
break;
//set MAP users
case 0x2aff:
case 0x2aff: //set MAP users
if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
//TODO: When data mismatches memory, update guild/party online/offline states.
@ -2887,9 +2886,7 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd,6+i*8);
break;
// キャラデータ保存
// Recieve character data from map-server
case 0x2b01:
case 0x2b01: // Receive character data from map-server for saving
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
for(i = 0; i < char_num; i++) {
@ -2902,28 +2899,28 @@ int parse_frommap(int fd) {
if (RFIFOB(fd,12))
{ //Flag, set character offline. [Skotlex]
set_char_offline(RFIFOL(fd,8),RFIFOL(fd,4));
WFIFOW(fd, 0) = 0x2b21; //Save ack only needed on final save.
WFIFOL(fd, 2) = RFIFOL(fd,4);
WFIFOL(fd, 6) = RFIFOL(fd,8);
WFIFOSET(fd, 10);
WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save.
WFIFOL(fd,2) = RFIFOL(fd,4);
WFIFOL(fd,6) = RFIFOL(fd,8);
WFIFOSET(fd,10);
}
RFIFOSKIP(fd,RFIFOW(fd,2));
break;
// キャラセレ要求
case 0x2b02:
case 0x2b02: // req char selection
if (RFIFOREST(fd) < 18)
return 0;
if (auth_fifo_pos >= AUTH_FIFO_SIZE)
auth_fifo_pos = 0;
auth_fifo[auth_fifo_pos].account_id = RFIFOL(fd,2);
auth_fifo[auth_fifo_pos].char_id = 0;
auth_fifo[auth_fifo_pos].login_id1 = RFIFOL(fd,6);
auth_fifo[auth_fifo_pos].login_id2 = RFIFOL(fd,10);
auth_fifo[auth_fifo_pos].delflag = 2;
auth_fifo[auth_fifo_pos].char_pos = 0;
auth_fifo[auth_fifo_pos].connect_until_time = 0; // unlimited/unknown time by default (not display in map-server)
auth_fifo[auth_fifo_pos].ip = RFIFOL(fd,14);
auth_fifo[auth_fifo_pos].ip = ntohl(RFIFOL(fd,14));
auth_fifo_pos++;
WFIFOW(fd,0) = 0x2b03;
WFIFOL(fd,2) = RFIFOL(fd,2);
@ -2932,8 +2929,7 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd,18);
break;
// request "change map server"
case 0x2b05:
case 0x2b05: // request "change map server"
if (RFIFOREST(fd) < 35)
return 0;
{
@ -2943,7 +2939,7 @@ int parse_frommap(int fd) {
struct mmo_charstatus* char_data;
name = RFIFOW(fd,18);
map_id = search_mapserver(name, RFIFOL(fd,24), 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)
map_fd = server_fd[map_id];
for(i = 0; i < char_num; i++) {
@ -2951,16 +2947,16 @@ int parse_frommap(int fd) {
char_dat[i].status.char_id == RFIFOL(fd,14))
break;
}
char_data = i< char_num? &char_dat[i].status:NULL;
char_data = i < char_num ? &char_dat[i].status : NULL;
//Tell the new map server about this player using Kevin's new auth packet. [Skotlex]
if (map_fd>=0 && session[map_fd] && char_data)
if (map_fd >= 0 && session[map_fd] && char_data)
{ //Send the map server the auth of this player.
//Update the "last map" as this is where the player must be spawned on the new map server.
WFIFOHEAD(map_fd, 20 + sizeof(struct mmo_charstatus));
char_data->last_point.map = RFIFOW(fd,18);
char_data->last_point.x = RFIFOW(fd,20);
char_data->last_point.y = RFIFOW(fd,22);
char_data->sex = RFIFOB(fd,30); // Buuyo^
char_data->sex = RFIFOB(fd,30);
WFIFOW(map_fd,0) = 0x2afd;
WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus);
@ -2988,8 +2984,7 @@ int parse_frommap(int fd) {
}
break;
// キャラ名検索
case 0x2b08:
case 0x2b08: // char name check
if (RFIFOREST(fd) < 6)
return 0;
for(i = 0; i < char_num; i++) {
@ -3006,8 +3001,7 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd,6);
break;
// it is a request to become GM
case 0x2b0a:
case 0x2b0a: // request to become GM
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
// printf("parse_frommap: change gm -> login, account: %d, pass: '%s'.\n", RFIFOL(fd,4), RFIFOP(fd,8));
@ -3026,8 +3020,7 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd, RFIFOW(fd,2));
break;
// Map server send information to change an email of an account -> login-server
case 0x2b0c:
case 0x2b0c: // Map server send information to change an email of an account -> login-server
if (RFIFOREST(fd) < 86)
return 0;
if (login_fd > 0) { // don't send request if no login-server
@ -3039,15 +3032,14 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd, 86);
break;
// Map server ask char-server about a character name to do some operations (all operations are transmitted to login-server)
case 0x2b0e:
case 0x2b0e: // Request from map-server to change a char's status (all operations are transmitted to login-server)
if (RFIFOREST(fd) < 44)
return 0;
{
char character_name[NAME_LENGTH];
int acc = RFIFOL(fd,2); // account_id of who ask (-1 if nobody)
memcpy(character_name, RFIFOP(fd,6), NAME_LENGTH-1);
character_name[NAME_LENGTH -1] = '\0';
character_name[NAME_LENGTH-1] = '\0';
// prepare answer
WFIFOW(fd,0) = 0x2b0f; // answer
WFIFOL(fd,2) = acc; // who want do operation
@ -3151,8 +3143,7 @@ int parse_frommap(int fd) {
// case 0x2b0f: Not used anymore, available for future use
// Update and send fame ranking list [DracoRPG]
case 0x2b10:
case 0x2b10: // Update and send fame ranking list
if (RFIFOREST(fd) < 12)
return 0;
{
@ -3181,8 +3172,7 @@ int parse_frommap(int fd) {
size = 0;
break;
}
if(!size)
break;
if(!size) break; //No list.
if(pos)
{
pos--; //Convert from pos to index.
@ -3200,10 +3190,11 @@ int parse_frommap(int fd) {
list[size-1].id = 0;
list[size-1].fame = 0;
}
// Find the position where the player has to be inserted
for(i = 0; i < size && fame < list[i].fame; i++);
// When found someone with less or as much fame, insert just above
if(i >= size) break;//Out of ranking.
// When found someone with less or as much fame, insert just above
memmove(list+i+1, list+i, (size-i-1) * sizeof(struct fame_list));
list[i].id = cid;
list[i].fame = fame;
@ -3217,38 +3208,33 @@ int parse_frommap(int fd) {
}
break;
// Recieve rates [Wizputer]
case 0x2b16:
case 0x2b16: // Recieve rates [Wizputer]
if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,8))
return 0;
// Txt doesn't need this packet, so just skip it
RFIFOSKIP(fd,RFIFOW(fd,8));
break;
// Character disconnected set online 0 [Wizputer]
case 0x2b17:
case 0x2b17: // Character disconnected set online 0 [Wizputer]
if (RFIFOREST(fd) < 6)
return 0;
set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6));
RFIFOSKIP(fd,10);
break;
// Reset all chars to offline [Wizputer]
case 0x2b18:
case 0x2b18: // Reset all chars to offline [Wizputer]
set_all_offline(id);
RFIFOSKIP(fd,2);
break;
// Character set online [Wizputer]
case 0x2b19:
case 0x2b19: // Character set online [Wizputer]
if (RFIFOREST(fd) < 6)
return 0;
set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6));
RFIFOSKIP(fd,10);
break;
// Build and send fame ranking lists [DracoRPG]
case 0x2b1a:
case 0x2b1a: // Build and send fame ranking lists [DracoRPG]
if (RFIFOREST(fd) < 2)
return 0;
char_read_fame_list();
@ -3256,14 +3242,14 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd,2);
break;
//Request to save status change data. [Skotlex]
case 0x2b1c:
case 0x2b1c: //Request to save status change data. [Skotlex]
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
{
#ifdef ENABLE_SC_SAVING
int count, aid, cid;
struct scdata *data;
aid = RFIFOL(fd, 4);
cid = RFIFOL(fd, 8);
count = RFIFOW(fd, 12);
@ -3279,14 +3265,14 @@ int parse_frommap(int fd) {
RFIFOSKIP(fd, RFIFOW(fd, 2));
break;
}
case 0x2736:
case 0x2736: // ip address update
if (RFIFOREST(fd) < 6) return 0;
ShowInfo("Updated IP address of Server #%d to %d.%d.%d.%d.\n",id,
(int)RFIFOB(fd,2),(int)RFIFOB(fd,3),
(int)RFIFOB(fd,4),(int)RFIFOB(fd,5));
server[id].ip = RFIFOL(fd, 2);
server[id].ip = ntohl(RFIFOL(fd, 2));
ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(server[id].ip));
RFIFOSKIP(fd,6);
break;
default:
// inter server処理に渡す
{
@ -3305,16 +3291,17 @@ int parse_frommap(int fd) {
return 0;
}
int search_mapserver(unsigned short map, long ip, short port) {
int search_mapserver(unsigned short map, uint32 ip, uint16 port)
{
int i, j;
for(i = 0; i < MAX_MAP_SERVERS; i++)
if (server_fd[i] >= 0)
if (server_fd[i] > 0)
for (j = 0; server[i].map[j]; j++)
if (server[i].map[j] == map) {
if (ip > 0 && server[i].ip != ip)
if (ip != (uint32)-1 && server[i].ip != ip)
continue;
if (port > 0 && server[i].port != port)
if (port != (uint16)-1 && server[i].port != port)
continue;
return i;
}
@ -3329,45 +3316,41 @@ static int char_mapif_init(int fd) {
//--------------------------------------------
// Test to know if an IP come from LAN or WAN.
// Rewrote: Adnvanced subnet check [LuzZza]
//--------------------------------------------
int lan_subnetcheck(long *p) {
int lan_subnetcheck(uint32 ip)
{
int i;
unsigned char *sbn, *msk, *src = (unsigned char *)p;
for(i=0; i<subnet_count; i++) {
for(i = 0; i < subnet_count; i++) {
if(subnet[i].subnet == (*p & subnet[i].mask)) {
sbn = (unsigned char *)&subnet[i].subnet;
msk = (unsigned char *)&subnet[i].mask;
if((subnet[i].subnet & subnet[i].mask) == (ip & subnet[i].mask)) {
ShowInfo("Subnet check [%u.%u.%u.%u]: Matches "CL_CYAN"%u.%u.%u.%u/%u.%u.%u.%u"CL_RESET"\n",
src[0], src[1], src[2], src[3], sbn[0], sbn[1], sbn[2], sbn[3], msk[0], msk[1], msk[2], msk[3]);
CONVIP(ip), CONVIP(subnet[i].subnet), CONVIP(subnet[i].mask));
return subnet[i].map_ip;
}
}
ShowInfo("Subnet check [%u.%u.%u.%u]: "CL_CYAN"WAN"CL_RESET"\n", src[0], src[1], src[2], src[3]);
ShowInfo("Subnet check [%u.%u.%u.%u]: "CL_CYAN"WAN"CL_RESET"\n", CONVIP(ip));
return 0;
}
int parse_char(int fd) {
int parse_char(int fd)
{
int i, ch;
unsigned short cmd;
char email[40];
int map_fd;
struct char_session_data *sd;
unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
long subnet_map_ip;
uint32 ipl = session[fd]->client_addr;
uint32 subnet_map_ip;
RFIFOHEAD(fd);
sd = (struct char_session_data*)session[fd]->session_data;
if (login_fd < 0)
if(login_fd < 0)
session[fd]->eof = 1;
if(session[fd]->eof) { // disconnect any player (already connected to char-server or coming back from map-server) if login-server is diconnected.
if (fd == login_fd)
@ -3384,7 +3367,7 @@ int parse_char(int fd) {
return 0;
}
while(RFIFOREST(fd) >= 2 && !session[fd]->eof) {
while(RFIFOREST(fd) >= 2) {
cmd = RFIFOW(fd,0);
// crc32のスキップ用
if( sd==NULL && // 未ログインor管理パケット
@ -3415,6 +3398,7 @@ int parse_char(int fd) {
{
int GM_value;
WFIFOHEAD(fd, 4);
if (sd) {
//Received again auth packet for already authentified account?? Discard it.
//TODO: Perhaps log this as a hack attempt?
@ -3425,7 +3409,8 @@ int parse_char(int fd) {
ShowInfo("Account Logged On; Account ID: %d (GM level %d).\n", RFIFOL(fd,2), GM_value);
else
ShowInfo("Account Logged On; Account ID: %d.\n", RFIFOL(fd,2));
sd = (struct char_session_data*)aCalloc(sizeof(struct char_session_data), 1);
CREATE(session[fd]->session_data, struct char_session_data, 1);
sd = (struct char_session_data*)session[fd]->session_data;
session[fd]->session_data = sd;
strncpy(sd->email, "no mail", 40); // put here a mail without '@' to refuse deletion if we don't receive the e-mail
sd->connect_until_time = 0; // unknow or illimited (not displaying on map-server)
@ -3441,14 +3426,14 @@ int parse_char(int fd) {
auth_fifo[i].account_id == sd->account_id &&
auth_fifo[i].login_id1 == sd->login_id1 &&
auth_fifo[i].login_id2 == sd->login_id2 && // relate to the versions higher than 18
auth_fifo[i].ip == session[fd]->client_addr.sin_addr.s_addr &&
auth_fifo[i].ip == session[fd]->client_addr &&
auth_fifo[i].delflag == 2)
; i++);
if (i < AUTH_FIFO_SIZE) {
auth_fifo[i].delflag = 1;
char_auth_ok(fd, sd);
} else { // authentification not found
} else { // authentication not found
if (login_fd > 0) { // don't send request if no login-server
WFIFOHEAD(login_fd,19);
WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account
@ -3456,12 +3441,12 @@ int parse_char(int fd) {
WFIFOL(login_fd,6) = sd->login_id1;
WFIFOL(login_fd,10) = sd->login_id2; // relate to the versions higher than 18
WFIFOB(login_fd,14) = sd->sex;
WFIFOL(login_fd,15) = session[fd]->client_addr.sin_addr.s_addr;
WFIFOL(login_fd,15) = htonl(session[fd]->client_addr);
WFIFOSET(login_fd,19);
} else { // if no login-server, we must refuse connection
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x6c;
WFIFOW(fd,2) = 0;
WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
}
}
@ -3469,7 +3454,7 @@ int parse_char(int fd) {
RFIFOSKIP(fd,17);
break;
case 0x66: // キャラ選択
case 0x66: // char select
FIFOSD_CHECK(3);
{
int char_num = RFIFOB(fd,2);
@ -3500,6 +3485,7 @@ int parse_char(int fd) {
// searching map server
i = search_mapserver(cd->last_point.map,-1,-1);
// if map is not found, we check major cities
if (i < 0) {
unsigned short j;
@ -3549,18 +3535,18 @@ int parse_char(int fd) {
char map_name[MAP_NAME_LENGTH];
snprintf(map_name, MAP_NAME_LENGTH, "%s.gat", mapindex_id2name(cd->last_point.map));
WFIFOHEAD(fd, 28);
WFIFOHEAD(fd,28);
WFIFOW(fd,0) = 0x71;
WFIFOL(fd,2) = cd->char_id;
memcpy(WFIFOP(fd,6), map_name, MAP_NAME_LENGTH);
// Advanced subnet check [LuzZza]
if((subnet_map_ip = lan_subnetcheck((long *)p)))
WFIFOL(fd,22) = subnet_map_ip;
if(subnet_map_ip = lan_subnetcheck(ipl))
WFIFOL(fd,22) = htonl(subnet_map_ip);
else
WFIFOL(fd,22) = server[i].ip;
WFIFOL(fd,22) = htonl(server[i].ip);
WFIFOW(fd,26) = server[i].port;
WFIFOW(fd,26) = server[i].port; // /!\ must be sent in intel host byte order /!\ (client bug)
WFIFOSET(fd,28);
ShowInfo("Character selection '%s' (account: %d, slot: %d).\n",
@ -3573,14 +3559,13 @@ int parse_char(int fd) {
auth_fifo[auth_fifo_pos].login_id1 = sd->login_id1;
auth_fifo[auth_fifo_pos].login_id2 = sd->login_id2;
auth_fifo[auth_fifo_pos].delflag = 0;
auth_fifo[auth_fifo_pos].char_pos = sd->found_char[ch];
auth_fifo[auth_fifo_pos].sex = sd->sex;
auth_fifo[auth_fifo_pos].connect_until_time = sd->connect_until_time;
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr;
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)
{ //0 Should not be a valid server_fd [Skotlex]
{
WFIFOHEAD(fd, 3);
ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
server_fd[i] = -1;
@ -3602,19 +3587,21 @@ int parse_char(int fd) {
memcpy(WFIFOP(map_fd,20), cd, sizeof(struct mmo_charstatus));
WFIFOSET(map_fd, WFIFOW(map_fd,2));
}
set_char_online(i, cd->char_id, cd->account_id);
auth_fifo_pos++;
}
break;
}
case 0x67: // 作成
case 0x67: // make new
FIFOSD_CHECK(37);
if(char_new == 0) //turn character creation on/off [Kevin]
i = -2;
else
i = make_new_char(fd, RFIFOP(fd,2));
//added some better fail reporting to client on the txt version [Kevin]
//'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3)
if (i < 0)
{
WFIFOHEAD(fd, 3);
@ -3634,6 +3621,7 @@ int parse_char(int fd) {
WFIFOW(fd,0) = 0x6d;
len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat[i].status);
WFIFOSET(fd,len);
RFIFOSKIP(fd,37);
}
for(ch = 0; ch < MAX_CHARS; ch++) {
@ -3642,19 +3630,23 @@ int parse_char(int fd) {
break;
}
}
break;
case 0x68: // delete char //Yor's Fix
case 0x68: // delete char
FIFOSD_CHECK(46);
{
int cid = RFIFOL(fd,2);
struct mmo_charstatus *cs = NULL;
WFIFOHEAD(fd, 46);
WFIFOHEAD(login_fd,46);
ShowInfo(CL_RED" Request Char Deletion:"CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
memcpy(email, RFIFOP(fd,6), 40);
RFIFOSKIP(fd,46);
if (e_mail_check(email) == 0)
strncpy(email, "a@a.com", 40); // default e-mail
// BEGIN HACK: "change email using the char deletion 'confirm email' menu"
// if we activated email creation and email is default email
if (email_creation != 0 && strcmp(sd->email, "a@a.com") == 0 && login_fd > 0) { // to modify an e-mail, login-server must be online
// if sended email is incorrect e-mail
@ -3688,6 +3680,8 @@ int parse_char(int fd) {
}
break;
}
// END HACK
// otherwise, we delete the character
if (strcmpi(email, sd->email) != 0) { // if it's an invalid email
WFIFOW(fd, 0) = 0x70;
@ -3695,16 +3689,18 @@ int parse_char(int fd) {
WFIFOSET(fd, 3);
break;
}
for (i = 0; i < MAX_CHARS; i++) {
if (sd->found_char[i] == -1) continue;
if (char_dat[sd->found_char[i]].status.char_id == cid) break;
}
if (i == MAX_CHARS) {
if (i == MAX_CHARS) { // Such a character does not exist in the account
WFIFOW(fd,0) = 0x70;
WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
break;
}
// deletion process
cs = &char_dat[sd->found_char[i]].status;
char_delete(cs);
@ -3734,36 +3730,37 @@ int parse_char(int fd) {
WFIFOSET(fd,2);
break;
}
case 0x2af8: // マップサーバーログイン
case 0x2af8: // login as map-server
if (RFIFOREST(fd) < 60)
return 0;
{
char *l_user = RFIFOP(fd, 2);
char *l_pass = RFIFOP(fd, 26);
char *l_user = RFIFOP(fd,2);
char *l_pass = RFIFOP(fd,26);
WFIFOHEAD(fd, 4+5*GM_num);
l_user[23] = '\0';
l_pass[23] = '\0';
WFIFOW(fd,0) = 0x2af9;
for(i = 0; i < MAX_MAP_SERVERS; i++) {
if (server_fd[i] < 0)
if (server_fd[i] <= 0)
break;
}
if (i == MAX_MAP_SERVERS ||
strcmp(l_user, userid) ||
strcmp(l_pass, passwd)){
strcmp(l_pass, passwd)) {
WFIFOB(fd,2) = 3;
WFIFOSET(fd,3);
RFIFOSKIP(fd,60);
} else {
int len;
WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
session[fd]->func_parse = parse_frommap;
server_fd[i] = fd;
server[i].ip = RFIFOL(fd,54);
server[i].port = RFIFOW(fd,58);
server[i].ip = ntohl(RFIFOL(fd,54));
server[i].port = ntohs(RFIFOW(fd,58));
server[i].users = 0;
memset(server[i].map, 0, sizeof(server[i].map));
WFIFOSET(fd,3);
RFIFOSKIP(fd,60);
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
char_mapif_init(fd);
@ -3777,18 +3774,17 @@ int parse_char(int fd) {
}
WFIFOW(fd,2) = len;
WFIFOSET(fd,len);
return 0;
}
}
break;
}
case 0x187: // Alive信号?
case 0x187: // Alive?
if (RFIFOREST(fd) < 6)
return 0;
RFIFOSKIP(fd, 6);
break;
case 0x7530: // Athena情報所得
case 0x7530: // Athena info get
{
WFIFOHEAD(fd, 10);
WFIFOW(fd,0) = 0x7531;
@ -3803,7 +3799,7 @@ int parse_char(int fd) {
RFIFOSKIP(fd,2);
return 0;
}
case 0x7532: // 接続の切断(defaultと処理は一緒だが明示的にするため)
case 0x7532: // disconnect(default also disconnect)
default:
session[fd]->eof = 1;
return 0;
@ -3850,22 +3846,14 @@ 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 0 //This seems to have been fixed long long ago.
if (session[fd] == NULL)
{ //Could this be the crash's source? [Skotlex]
ShowError("mapif_sendall: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", fd, i);
server_fd[i] = -1;
memset(&server[i], 0, sizeof(struct mmo_map_server));
continue;
}
#endif
WFIFOHEAD(fd, len);
if ((fd = server_fd[i]) > 0) {
WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len);
c++;
}
}
return c;
}
@ -3876,15 +3864,14 @@ 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_fd[i]) > 0 && fd != sfd) {
WFIFOHEAD(fd, len);
if (WFIFOSPACE(fd) < len) //Increase buffer size.
realloc_writefifo(fd, len);
memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd, len);
c++;
}
}
return c;
}
// MAPサーバーにデータ送信map鯖生存確認有り
@ -3894,9 +3881,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]) {
WFIFOHEAD(fd, len);
if (WFIFOSPACE(fd) < len) //Increase buffer size.
realloc_writefifo(fd, len);
WFIFOHEAD(fd,len);
memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len);
return 1;
@ -3912,7 +3897,7 @@ int send_users_tologin(int tid, unsigned int tick, int id, int data) {
if (login_fd > 0 && session[login_fd]) {
// send number of user to login server
WFIFOHEAD(login_fd, 6);
WFIFOHEAD(login_fd,6);
WFIFOW(login_fd,0) = 0x2714;
WFIFOL(login_fd,2) = users;
WFIFOSET(login_fd,6);
@ -3962,26 +3947,26 @@ int check_connect_login_server(int tid, unsigned int tick, int id, int data) {
ShowInfo("Attempt to connect to login-server...\n");
login_fd = make_connection(login_ip, login_port);
if (login_fd == -1)
{ //Try again later... [Skotlex]
{ //Try again later. [Skotlex]
login_fd = 0;
return 0;
}
session[login_fd]->func_parse = parse_tologin;
realloc_fifo(login_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
{
WFIFOHEAD(login_fd, 86);
WFIFOW(login_fd,0) = 0x2710;
memcpy(WFIFOP(login_fd,2), userid, 24);
memcpy(WFIFOP(login_fd,26), passwd, 24);
WFIFOL(login_fd,50) = 0;
WFIFOL(login_fd,54) = char_ip;
WFIFOL(login_fd,58) = char_port;
WFIFOL(login_fd,54) = htonl(char_ip);
WFIFOL(login_fd,58) = htons(char_port);
memcpy(WFIFOP(login_fd,60), server_name, 20);
WFIFOW(login_fd,80) = 0;
WFIFOW(login_fd,82) = char_maintenance;
WFIFOW(login_fd,84) = char_new_display; //only display (New) if they want to [Kevin]
WFIFOSET(login_fd,86);
}
return 1;
}
@ -4050,9 +4035,9 @@ int char_lan_config_read(const char *lancfgName) {
if(strcmpi(w1, "subnet") == 0) {
subnet[subnet_count].mask = inet_addr(w2);
subnet[subnet_count].char_ip = inet_addr(w3);
subnet[subnet_count].map_ip = inet_addr(w4);
subnet[subnet_count].mask = ntohl(inet_addr(w2));
subnet[subnet_count].char_ip = ntohl(inet_addr(w3));
subnet[subnet_count].map_ip = ntohl(inet_addr(w4));
subnet[subnet_count].subnet = subnet[subnet_count].char_ip&subnet[subnet_count].mask;
if (subnet[subnet_count].subnet != (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);
@ -4072,7 +4057,7 @@ int char_lan_config_read(const char *lancfgName) {
int char_config_read(const char *cfgName) {
char line[1024], w1[1024], w2[1024];
FILE *fp = fopen(cfgName, "r");
FILE* fp = fopen(cfgName, "r");
if (fp == NULL) {
ShowFatalError("Configuration file not found: %s.\n", cfgName);
@ -4173,9 +4158,9 @@ int char_config_read(const char *cfgName) {
} else if (strcmpi(w1, "save_log") == 0) {
save_log = config_switch(w2);
} else if (strcmpi(w1, "start_point") == 0) {
char map[32];
char map[MAP_NAME_LENGTH];
int x, y;
if (sscanf(w2, "%[^,],%d,%d", map, &x, &y) < 3)
if (sscanf(w2, "%16[^,],%d,%d", map, &x, &y) < 3)
continue;
start_point.map = mapindex_name2id(map);
if (!start_point.map) {
@ -4184,8 +4169,6 @@ int char_config_read(const char *cfgName) {
}
start_point.x = x;
start_point.y = y;
} else if(strcmpi(w1,"log_char")==0) { //log char or not [devil]
log_char = atoi(w2);
} else if (strcmpi(w1, "start_zeny") == 0) {
start_zeny = atoi(w2);
if (start_zeny < 0)
@ -4198,6 +4181,8 @@ int char_config_read(const char *cfgName) {
start_armor = atoi(w2);
if (start_armor < 0)
start_armor = 0;
} else if(strcmpi(w1,"log_char")==0) { //log char or not [devil]
log_char = atoi(w2);
} else if (strcmpi(w1, "unknown_char_name") == 0) {
strcpy(unknown_char_name, w2);
unknown_char_name[NAME_LENGTH-1] = '\0';
@ -4326,7 +4311,8 @@ static int online_data_cleanup(int tid, unsigned int tick, int id, int data)
return 0;
}
int do_init(int argc, char **argv) {
int do_init(int argc, char **argv)
{
int i;
mapindex_init(); //Needed here for the start-point reading.
@ -4345,23 +4331,21 @@ int do_init(int argc, char **argv) {
// moved behind char_config_read in case we changed the filename [celest]
char_log("The char-server starting..." RETCODE);
if ((naddr_ != 0) && (!login_ip || !char_ip)) {
// The char server should know what IP address it is running on
// - MouseJstr
int localaddr = ntohl(addr_[0]);
unsigned char *ptr = (unsigned char *) &localaddr;
char buf[16];
sprintf(buf, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);;
if (naddr_ != 1)
ShowStatus("Multiple interfaces detected.. using %s as our IP address\n", buf);
if ((naddr_ != 0) && (!login_ip || !char_ip))
{
char ip_str[16];
ip2str(addr_[0], ip_str);
if (naddr_ > 1)
ShowStatus("Multiple interfaces detected.. using %s as our IP address\n", ip_str);
else
ShowStatus("Defaulting to %s as our IP address\n", buf);
ShowStatus("Defaulting to %s as our IP address\n", ip_str);
if (!login_ip) {
strcpy(login_ip_str, buf);
strcpy(login_ip_str, ip_str);
login_ip = inet_addr(login_ip_str);
}
if (!char_ip) {
strcpy(char_ip_str, buf);
strcpy(char_ip_str, ip_str);
char_ip = inet_addr(char_ip_str);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -215,8 +215,8 @@ struct mmo_charstatus {
short str,agi,vit,int_,dex,luk;
unsigned char char_num,sex;
unsigned long mapip;
unsigned int mapport;
uint32 mapip;
uint16 mapport;
struct point last_point,save_point,memo_point[MAX_MEMOPOINTS];
struct item inventory[MAX_INVENTORY],cart[MAX_CART];

View File

@ -242,7 +242,7 @@ int connect_client(int listen_fd)
len = sizeof(client_address);
fd = accept(listen_fd,(struct sockaddr*)&client_address,&len);
fd = accept(listen_fd, (struct sockaddr*)&client_address, &len);
if ( fd == INVALID_SOCKET ) {
ShowError("accept failed (code %i)!\n", s_errno);
return -1;
@ -258,7 +258,7 @@ int connect_client(int listen_fd)
set_nonblocking(fd, 1);
#ifndef MINICORE
if( ip_rules && !connect_check(*(uint32*)(&client_address.sin_addr)) ){
if( ip_rules && !connect_check(ntohl(client_address.sin_addr.s_addr)) ) {
do_close(fd);
return -1;
}
@ -270,13 +270,13 @@ int connect_client(int listen_fd)
fd_max = fd + 1;
create_session(fd, recv_to_fifo, send_from_fifo, default_func_parse);
session[fd]->client_addr = client_address;
session[fd]->client_addr = ntohl(client_address.sin_addr.s_addr);
session[fd]->rdata_tick = last_tick;
return fd;
}
int make_listen_bind(long ip,int port)
int make_listen_bind(uint32 ip, uint16 port)
{
struct sockaddr_in server_address;
int fd;
@ -293,8 +293,8 @@ int make_listen_bind(long ip,int port)
set_nonblocking(fd, 1);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = ip;
server_address.sin_port = htons((unsigned short)port);
server_address.sin_addr.s_addr = htonl(ip);
server_address.sin_port = htons(port);
result = bind(fd, (struct sockaddr*)&server_address, sizeof(server_address));
if( result == SOCKET_ERROR ) {
@ -320,7 +320,7 @@ int make_listen_bind(long ip,int port)
return fd;
}
int make_connection(long ip, int port)
int make_connection(uint32 ip, uint16 port)
{
struct sockaddr_in server_address;
int fd;
@ -336,11 +336,10 @@ int make_connection(long ip, int port)
setsocketopts(fd);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = ip;
server_address.sin_port = htons((unsigned short)port);
server_address.sin_addr.s_addr = htonl(ip);
server_address.sin_port = htons(port);
ShowStatus("Connecting to %d.%d.%d.%d:%i\n",
(ip)&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,(ip>>24)&0xFF,port);
ShowStatus("Connecting to %d.%d.%d.%d:%i\n", CONVIP(ip), port);
result = connect(fd, (struct sockaddr *)(&server_address), sizeof(struct sockaddr_in));
if( result == SOCKET_ERROR ) {
@ -389,7 +388,7 @@ int delete_session(int fd)
return 0;
}
int realloc_fifo(int fd,unsigned int rfifo_size,unsigned int wfifo_size)
int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size)
{
if( !session_isValid(fd) )
return 0;
@ -421,7 +420,7 @@ int realloc_writefifo(int fd, size_t addition)
else if( session[fd]->max_wdata >= FIFOSIZE_SERVERLINK) {
//Inter-server adjust. [Skotlex]
if ((session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata)
newsize = session[fd]->max_wdata/2;
newsize = session[fd]->max_wdata / 2;
else
return 0; //No change
} else if( session[fd]->max_wdata > wfifo_size && (session[fd]->wdata_size+addition)*4 < session[fd]->max_wdata )
@ -437,7 +436,7 @@ int realloc_writefifo(int fd, size_t addition)
return 0;
}
int RFIFOSKIP(int fd,int len)
int RFIFOSKIP(int fd, int len)
{
struct socket_data *s;
@ -468,11 +467,10 @@ int WFIFOSET(int fd, int len)
// we have written len bytes to the buffer already before calling WFIFOSET
if(s->wdata_size+len > s->max_wdata)
{ // actually there was a buffer overflow already
unsigned char *sin_addr = (unsigned char *)&s->client_addr.sin_addr;
ShowFatalError("socket: Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n", fd,
sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3], len, s->wdata_size, s->max_wdata);
ShowDebug("Likely command that caused it: 0x%x\n",
(*(unsigned short*)(s->wdata + s->wdata_size)));
uint32 ip = s->client_addr;
ShowFatalError("socket: Buffer Overflow. Connection %d (%d.%d.%d.%d) has written %d bytes on a %d/%d bytes buffer.\n",
fd, CONVIP(ip), len, s->wdata_size, s->max_wdata);
ShowDebug("Likely command that caused it: 0x%x\n", (*(unsigned short*)(s->wdata + s->wdata_size)));
// no other chance, make a better fifo model
exit(1);
}
@ -652,8 +650,6 @@ static int ddos_autoreset = 10*60*1000;
/// The array's index for any ip is ip&0xFFFF
static ConnectHistory* connect_history[0x10000];
#define CONVIP(ip) ip&0xFF,(ip>>8)&0xFF,(ip>>16)&0xFF,ip>>24
static int connect_check_(uint32 ip);
/// Verifies if the IP can connect. (with debug info)
@ -816,7 +812,7 @@ int access_ipmask(const char* str, AccessControl* acc)
unsigned int m[4];
int n;
if( strcmp(str,"all") == 0 ){
if( strcmp(str,"all") == 0 ) {
ip = 0;
mask = 0;
} else {
@ -856,7 +852,7 @@ int access_ipmask(const char* str, AccessControl* acc)
#endif
//////////////////////////////
int socket_config_read(const char *cfgName)
int socket_config_read(const char* cfgName)
{
char line[1024],w1[1024],w2[1024];
FILE *fp;
@ -960,7 +956,7 @@ void do_close(int fd)
/// Retrieve local ips in host byte order.
/// Uses loopback is no address is found.
int socket_getips(uint32 *ips, int max)
int socket_getips(uint32* ips, int max)
{
int num = 0;
@ -986,7 +982,7 @@ int socket_getips(uint32 *ips, int max)
{
hent = gethostbyname(fullhost);
if( hent == NULL ){
ShowError("socket_getips: Cannot resolve our own hostname to a IP address\n");
ShowError("socket_getips: Cannot resolve our own hostname to an IP address\n");
return 0;
}
a = (u_long**)hent->h_addr_list;
@ -1099,16 +1095,18 @@ int session_isActive(int fd)
return ( session_isValid(fd) && !session[fd]->eof );
}
in_addr_t host2ip(const char* hostname)
// Resolves hostname into a numeric ip.
uint32 host2ip(const char* hostname)
{
struct hostent* h = gethostbyname(hostname);
return (h != NULL) ? *(in_addr_t*)h->h_addr : 0;
return (h != NULL) ? ntohl(*(uint32*)h->h_addr) : 0;
}
const char* ip2str(in_addr_t ip, char ip_str[16])
// Converts a numeric ip into a dot-formatted string.
// Result is placed either into a user-provided buffer or a static system buffer.
const char* ip2str(uint32 ip, char ip_str[16])
{
in_addr_t addr = ntohl(ip);
sprintf(ip_str, "%d.%d.%d.%d", (addr>>24)&0xFF, (addr>>16)&0xFF, (addr>>8)&0xFF, (addr>>0)&0xFF);
return ip_str;
struct in_addr addr;
addr.s_addr = htonl(ip);
return (ip_str == NULL) ? inet_ntoa(addr) : strncpy(ip_str, inet_ntoa(addr), 16);
}

View File

@ -81,7 +81,7 @@ struct socket_data {
size_t rdata_size, wdata_size;
size_t rdata_pos;
time_t rdata_tick; // time of last receive (for detecting timeouts)
struct sockaddr_in client_addr; // remote client address (zero for s2s connections)
uint32 client_addr; // remote client address (zero for s2s connections)
void* session_data;
RecvFunc func_recv;
SendFunc func_send;
@ -106,12 +106,12 @@ extern int session_isActive(int fd);
// Function prototype declaration
int make_listen_bind(long,int);
int make_connection(long,int);
int realloc_fifo(int fd,unsigned int rfifo_size,unsigned int wfifo_size);
int make_listen_bind(uint32 ip, uint16 port);
int make_connection(uint32 ip, uint16 port);
int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size);
int realloc_writefifo(int fd, size_t addition);
int WFIFOSET(int fd,int len);
int RFIFOSKIP(int fd,int len);
int WFIFOSET(int fd, int len);
int RFIFOSKIP(int fd, int len);
int do_sendrecv(int next);
int do_parsepacket(void);
@ -126,9 +126,9 @@ extern void set_nonblocking(int fd, int yes);
void set_defaultparse(ParseFunc defaultparse);
// hostname/ip conversion functions
in_addr_t host2ip(const char* hostname);
const char* ip2str(in_addr_t ip, char ip_str[16]);
uint32 host2ip(const char* hostname);
const char* ip2str(uint32 ip, char ip_str[16]);
#define CONVIP(ip) (ip>>24)&0xFF,(ip>>16)&0xFF,(ip>>8)&0xFF,(ip>>0)&0xFF
int socket_getips(uint32* ips, int max);

View File

@ -11,12 +11,15 @@
#include "../common/utils.h"
#include "../common/malloc.h"
//-----------------------------------------------
// string lib.
char* jstrescape (char* pt) {
#define J_MAX_MALLOC_SIZE 65535
// escapes a string in-place (' -> \' , \ -> \\ , % -> _)
char* jstrescape (char* pt)
{
//copy from here
char *ptr;
int i =0, j=0;
int i = 0, j = 0;
//copy string to temporary
CREATE(ptr, char, J_MAX_MALLOC_SIZE);
@ -41,10 +44,12 @@ char* jstrescape (char* pt) {
}
pt[j++] = '\0';
aFree(ptr);
return &pt[0];
return pt;
}
char* jstrescapecpy (char* pt, const char* spt) {
// escapes a string into a provided buffer
char* jstrescapecpy (char* pt, const char* spt)
{
//copy from here
//WARNING: Target string pt should be able to hold strlen(spt)*2, as each time
//a escape character is found, the target's final length increases! [Skotlex]
@ -75,7 +80,10 @@ char* jstrescapecpy (char* pt, const char* spt) {
pt[j++] = '\0';
return &pt[0];
}
int jmemescapecpy (char* pt,char* spt, int size) {
// escapes exactly 'size' bytes of a string into a provided buffer
int jmemescapecpy (char* pt, const char* spt, int size)
{
//copy from here
int i =0, j=0;
@ -100,11 +108,9 @@ int jmemescapecpy (char* pt,char* spt, int size) {
return j;
}
//-----------------------------------------------------
// Function to suppress control characters in a string.
//-----------------------------------------------------
//int remove_control_chars(char *str) {
int remove_control_chars(unsigned char *str) {
int remove_control_chars(char* str)
{
int i;
int change = 0;
@ -119,11 +125,11 @@ int remove_control_chars(unsigned char *str) {
}
//Trims a string, also removes illegal characters such as \t and reduces continous spaces to a single one. by [Foruken]
char *trim(char *str, const char *delim)
char* trim(char* str, const char* delim)
{
char *strp = strtok(str,delim);
char* strp = strtok(str,delim);
char buf[1024];
char *bufp = buf;
char* bufp = buf;
memset(buf,0,sizeof buf);
while(strp) {
@ -143,7 +149,7 @@ char *trim(char *str, const char *delim)
//stristr: Case insensitive version of strstr, code taken from
//http://www.daniweb.com/code/snippet313.html, Dave Sinkula
//
const char *stristr(const char *haystack, const char *needle)
const char* stristr(const char* haystack, const char* needle)
{
if ( !*needle )
{
@ -153,9 +159,7 @@ const char *stristr(const char *haystack, const char *needle)
{
if ( TOUPPER(*haystack) == TOUPPER(*needle) )
{
/*
* Matched starting char -- loop through remaining chars.
*/
// matched starting char -- loop through remaining chars
const char *h, *n;
for ( h = haystack, n = needle; *h && *n; ++h, ++n )
{
@ -164,9 +168,9 @@ const char *stristr(const char *haystack, const char *needle)
break;
}
}
if ( !*n ) /* matched all of 'needle' to null termination */
if ( !*n ) // matched all of 'needle' to null termination
{
return haystack; /* return the start of the match */
return haystack; // return the start of the match
}
}
}
@ -174,7 +178,7 @@ const char *stristr(const char *haystack, const char *needle)
}
#ifdef __WIN32
char *_strtok_r(char *s1, const char *s2, char **lasts)
char* _strtok_r(char *s1, const char *s2, char **lasts)
{
char *ret;

View File

@ -4,25 +4,20 @@
#ifndef _STRLIB_H_
#define _STRLIB_H_
#define J_MAX_MALLOC_SIZE 65535
// String function library.
// code by Jioh L. Jung (ziozzang@4wish.net)
// This code is under license "BSD"
char* jstrescape (char* pt);
char* jstrescapecpy (char* pt, const char* spt);
int jmemescapecpy (char* pt,char* spt, int size);
int jmemescapecpy (char* pt, const char* spt, int size);
int remove_control_chars(char *);
char *trim(char *str, const char *delim);
const char *stristr(const char *haystack, const char *needle);
#ifdef __WIN32
#define HAVE_STRTOK_R
#define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr))
char *_strtok_r(char *s1, const char *s2, char **lasts);
char* _strtok_r(char* s1, const char* s2, char** lasts);
#endif
// custom functions
int remove_control_chars(unsigned char *);
char *trim(char *str, const char *delim);
const char *stristr(const char *haystack, const char *needle);
#if !defined(WIN32) || (defined(_MSC_VER) && _MSC_VER < 1400)
size_t strnlen (const char* string, size_t maxlen);
#endif

View File

@ -20,28 +20,28 @@
#include "../common/showmsg.h"
#include "../common/cbasetypes.h"
void dump(unsigned char *buffer, int num)
void dump(unsigned char* buffer, int num)
{
int icnt,jcnt;
int icnt, jcnt;
printf(" Hex ASCII\n");
printf(" ----------------------------------------------- ----------------");
for (icnt=0;icnt<num;icnt+=16) {
printf("\n%p ",&buffer[icnt]);
for (jcnt=icnt;jcnt<icnt+16;++jcnt) {
for (icnt = 0; icnt < num; icnt += 16) {
printf("\n%p ", &buffer[icnt]);
for (jcnt = icnt; jcnt < icnt + 16; ++jcnt) {
if (jcnt < num) {
printf("%02hX ",buffer[jcnt]);
printf("%02hX ", buffer[jcnt]);
} else
printf(" ");
}
printf(" | ");
for (jcnt=icnt;jcnt<icnt+16;++jcnt) {
for (jcnt = icnt; jcnt < icnt + 16; ++jcnt) {
if (jcnt < num) {
if (buffer[jcnt] > 31 && buffer[jcnt] < 127)
printf("%c",buffer[jcnt]);
printf("%c", buffer[jcnt]);
else
printf(".");
} else
@ -266,30 +266,20 @@ void findfile(const char *p, const char *pat, void (func)(const char*))
unsigned char GetByte(unsigned long val, size_t num)
{
switch(num)
{
case 0:
return (unsigned char)((val & 0x000000FF) );
case 1:
return (unsigned char)((val & 0x0000FF00)>>0x08);
case 2:
return (unsigned char)((val & 0x00FF0000)>>0x10);
case 3:
return (unsigned char)((val & 0xFF000000)>>0x18);
default:
return 0; //better throw something here
switch(num) {
case 0: return (unsigned char)((val & 0x000000FF) );
case 1: return (unsigned char)((val & 0x0000FF00)>>0x08);
case 2: return (unsigned char)((val & 0x00FF0000)>>0x10);
case 3: return (unsigned char)((val & 0xFF000000)>>0x18);
default: return 0; //better throw something here
}
}
unsigned short GetWord(unsigned long val, size_t num)
{
switch(num)
{
case 0:
return (unsigned short)((val & 0x0000FFFF) );
case 1:
return (unsigned short)((val & 0xFFFF0000)>>0x10);
default:
return 0; //better throw something here
switch(num) {
case 0: return (unsigned short)((val & 0x0000FFFF) );
case 1: return (unsigned short)((val & 0xFFFF0000)>>0x10);
default: return 0; //better throw something here
}
}
unsigned short MakeWord(unsigned char byte0, unsigned char byte1)

View File

@ -39,15 +39,15 @@
int account_id_count = START_ACCOUNT_NUM;
int server_num;
int new_account_flag = 0;
in_addr_t login_ip = INADDR_ANY;
uint32 login_ip = INADDR_ANY;
int login_port = 6900;
// Advanced subnet check [LuzZza]
struct _subnet {
long subnet;
long mask;
long char_ip;
long map_ip;
uint32 subnet;
uint32 mask;
uint32 char_ip;
uint32 map_ip;
} subnet[16];
int subnet_count = 0;
@ -116,7 +116,9 @@ struct login_session_data {
#define AUTH_FIFO_SIZE 256
struct {
int account_id, login_id1, login_id2;
int ip, sex, delflag;
uint32 ip;
char sex;
bool delflag;
} auth_fifo[AUTH_FIFO_SIZE];
int auth_fifo_pos = 0;
@ -379,36 +381,36 @@ int read_gm_account(void) {
// Test of the IP mask
// (ip: IP to be tested, str: mask x.x.x.x/# or x.x.x.x/y.y.y.y)
//--------------------------------------------------------------
int check_ipmask(unsigned int ip, const unsigned char *str) {
unsigned int mask = 0, i = 0, m, ip2, a0, a1, a2, a3;
int check_ipmask(uint32 ip, const unsigned char *str)
{
unsigned int i = 0, m = 0;
unsigned int ip2, mask = 0;
unsigned char *p = (unsigned char *)&ip2, *p2 = (unsigned char *)&mask;
if (sscanf((const char*)str, "%d.%d.%d.%d/%n", &a0, &a1, &a2, &a3, &i) != 4 || i == 0)
// scan ip address
if (sscanf((const char*)str, "%d.%d.%d.%d/%n", &p[3], &p[2], &p[1], &p[0], &i) != 4 || i == 0)
return 0;
p[0] = a0; p[1] = a1; p[2] = a2; p[3] = a3;
if (sscanf((const char*)str+i, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) == 4) {
p2[0] = a0; p2[1] = a1; p2[2] = a2; p2[3] = a3;
mask = ntohl(mask);
// scan mask
if (sscanf((const char*)str+i, "%d.%d.%d.%d", &p2[3], &p2[2], &p2[1], &p2[0]) == 4) {
;
} else if (sscanf((const char*)(str+i), "%d", &m) == 1 && m >= 0 && m <= 32) {
for(i = 0; i < m && i < 32; i++)
mask = (mask >> 1) | 0x80000000;
mask |= (1 << i);
} else {
ShowError("check_ipmask: invalid mask [%s].\n", str);
return 0;
}
// printf("Tested IP: %08x, network: %08x, network mask: %08x\n",
// (unsigned int)ntohl(ip), (unsigned int)ntohl(ip2), (unsigned int)mask);
return ((ntohl(ip) & mask) == (ntohl(ip2) & mask));
return ((ip & mask) == (ip2 & mask));
}
//---------------------
// Access control by IP
//---------------------
int check_ip(unsigned int ip) {
int check_ip(uint32 ip)
{
int i;
unsigned char *p = (unsigned char *)&ip;
char buf[20];
char * access_ip;
enum { ACF_DEF, ACF_ALLOW, ACF_DENY } flag = ACF_DEF;
@ -425,7 +427,7 @@ int check_ip(unsigned int ip) {
// If we have an answer, there is no guarantee to have a 100% correct value.
// And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
// So, DNS notation isn't authorised for ip checking.
sprintf(buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
sprintf(buf, "%d.%d.%d.%d.", CONVIP(ip));
for(i = 0; i < access_allownum; i++) {
access_ip = access_allow + i * ACO_STRSIZE;
@ -455,9 +457,9 @@ int check_ip(unsigned int ip) {
//--------------------------------
// Access control by IP for ladmin
//--------------------------------
int check_ladminip(unsigned int ip) {
int check_ladminip(uint32 ip)
{
int i;
unsigned char *p = (unsigned char *)&ip;
char buf[20];
char * access_ip;
@ -473,7 +475,7 @@ int check_ladminip(unsigned int ip) {
// If we have an answer, there is no guarantee to have a 100% correct value.
// And, the waiting time (to check) can be long (over 1 minute to a timeout). That can block the software.
// So, DNS notation isn't authorised for ip checking.
sprintf(buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]);
sprintf(buf, "%d.%d.%d.%d.", CONVIP(ip));
for(i = 0; i < access_ladmin_allownum; i++) {
access_ip = access_ladmin_allow + i * ACO_STRSIZE;
@ -488,7 +490,8 @@ int check_ladminip(unsigned int ip) {
//---------------------------------------------------
// E-mail check: return 0 (not correct) or 1 (valid).
//---------------------------------------------------
int e_mail_check(char *email) {
int e_mail_check(char *email)
{
char ch;
char* last_arobas;
@ -562,12 +565,10 @@ int mmo_auth_tostr(char *str, struct auth_dat *p) {
int i;
char *str_p = str;
str_p += sprintf(str_p, "%d\t%s\t%s\t%s\t%c\t%d\t%d\t"
"%s\t%s\t%ld\t%s\t%s\t%ld\t",
str_p += sprintf(str_p, "%d\t%s\t%s\t%s\t%c\t%d\t%d\t%s\t%s\t%ld\t%s\t%s\t%ld\t",
p->account_id, p->userid, p->pass, p->lastlogin,
(p->sex == 2) ? 'S' : (p->sex ? 'M' : 'F'),
p->logincount, p->state,
p->email, p->error_message,
p->sex == 2 ? 'S' : p->sex == 1 ? 'M' : 'F',
p->logincount, p->state, p->email, p->error_message,
(long)p->connect_until_time, p->last_ip, p->memo, (long)p->ban_until_time);
for(i = 0; i < p->account_reg2_num; i++)
@ -998,7 +999,8 @@ int check_auth_sync(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, unsigned char *buf, unsigned int len) {
int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
{
int i, c, fd;
for(i = 0, c = 0; i < MAX_SERVERS; i++) {
@ -1011,13 +1013,15 @@ int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) {
c++;
}
}
return c;
}
//-----------------------------------------------------
// Send GM accounts to all char-server
//-----------------------------------------------------
void send_GM_accounts(void) {
void send_GM_accounts(void)
{
unsigned int i;
unsigned char buf[32767];
int len;
@ -1035,6 +1039,7 @@ void send_GM_accounts(void) {
break;
}
}
WBUFW(buf,2) = len;
charif_sendallwos(-1, buf, len);
@ -1069,7 +1074,8 @@ int check_GM_file(int tid, unsigned int tick, int id, int data) {
//-------------------------------------
// Account creation (with e-mail check)
//-------------------------------------
int mmo_auth_new(struct mmo_account* account, char sex, char* email) {
int mmo_auth_new(struct mmo_account* account, char sex, char* email)
{
time_t timestamp, timestamp_temp;
struct tm *tmtime;
int i = auth_num;
@ -1085,28 +1091,14 @@ int mmo_auth_new(struct mmo_account* account, char sex, char* email) {
account_id_count++;
auth_dat[i].account_id = account_id_count++;
strncpy(auth_dat[i].userid, account->userid, NAME_LENGTH);
auth_dat[i].userid[23] = '\0';
strncpy(auth_dat[i].pass, account->passwd, NAME_LENGTH);
auth_dat[i].pass[23] = '\0';
strncpy(auth_dat[i].userid, account->userid, NAME_LENGTH); auth_dat[i].userid[23] = '\0';
strncpy(auth_dat[i].pass, account->passwd, NAME_LENGTH); auth_dat[i].pass[23] = '\0';
memcpy(auth_dat[i].lastlogin, "-", 2);
auth_dat[i].sex = (sex == 'M' || sex == 'm');
auth_dat[i].logincount = 0;
auth_dat[i].state = 0;
if (e_mail_check(email) == 0)
strncpy(auth_dat[i].email, "a@a.com", 40);
else
strncpy(auth_dat[i].email, email, 40);
strncpy(auth_dat[i].email, e_mail_check(email) ? email : "a@a.com", 40);
strncpy(auth_dat[i].error_message, "-", 20);
auth_dat[i].ban_until_time = 0;
if (start_limited_time < 0)
@ -1123,9 +1115,7 @@ int mmo_auth_new(struct mmo_account* account, char sex, char* email) {
}
strncpy(auth_dat[i].last_ip, "-", 16);
strncpy(auth_dat[i].memo, "-", 255);
auth_dat[i].account_reg2_num = 0;
auth_num++;
@ -1151,8 +1141,8 @@ int mmo_auth(struct mmo_account* account, int fd)
char user_password[256];
char ip[16];
unsigned char *sin_addr = (unsigned char *)&session[fd]->client_addr.sin_addr;
sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
uint8* sin_addr = (uint8*)&session[fd]->client_addr;
sprintf(ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]);
// DNS Blacklist check
if(use_dnsbl)
@ -1162,7 +1152,7 @@ int mmo_auth(struct mmo_account* account, int fd)
char *dnsbl_serv;
bool matched = false;
sprintf(r_ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]);
sprintf(r_ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
for (dnsbl_serv = strtok(dnsbl_servs,","); dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,","))
{
@ -1312,16 +1302,16 @@ int mmo_auth(struct mmo_account* account, int fd)
}
if (online_check) {
unsigned char buf[8];
struct online_login_data* data = idb_get(online_db,auth_dat[i].account_id);
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);
WBUFW(buf,0) = 0x2734;
WBUFL(buf,2) = auth_dat[i].account_id;
charif_sendallwos(-1, buf, 6);
if (data->waiting_disconnect == -1)
data->waiting_disconnect = add_timer(gettick()+30000, waiting_disconnect_timer,auth_dat[i].account_id, 0);
data->waiting_disconnect = add_timer(gettick()+30000, waiting_disconnect_timer, auth_dat[i].account_id, 0);
return 3; // Rejected
}
}
@ -1394,7 +1384,8 @@ int mmo_auth(struct mmo_account* account, int fd)
return -1; // account OK
}
static int online_db_setoffline(DBKey key, void* data, va_list ap) {
static int online_db_setoffline(DBKey key, void* data, va_list ap)
{
struct online_login_data *p = (struct online_login_data *)data;
int server = va_arg(ap, int);
if (server == -1) {
@ -1412,26 +1403,26 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap) {
//--------------------------------
// Packet parsing for char-servers
//--------------------------------
int parse_fromchar(int fd) {
int parse_fromchar(int fd)
{
unsigned int i;
int j, id;
unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
uint32 ipl = session[fd]->client_addr;
char ip[16];
int acc;
RFIFOHEAD(fd);
sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
ip2str(ipl, ip);
for(id = 0; id < MAX_SERVERS; id++)
if (server_fd[id] == fd)
break;
if (id == MAX_SERVERS)
session[fd]->eof = 1;
if(session[fd]->eof) {
if (id < MAX_SERVERS) {
ShowStatus("Char-server '%s' has disconnected.\n", server[id].name);
login_log("Char-server '%s' has disconnected (ip: %s)." RETCODE,
server[id].name, ip);
login_log("Char-server '%s' has disconnected (ip: %s)." RETCODE, server[id].name, ip);
server_fd[id] = -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.
@ -1446,8 +1437,8 @@ int parse_fromchar(int fd) {
ShowDebug("parse_fromchar: connection #%d, packet: 0x%x (with being read: %d bytes).\n", fd, RFIFOW(fd,0), RFIFOREST(fd));
switch (RFIFOW(fd,0)) {
// request from map-server via char-server to reload GM accounts (by Yor).
case 0x2709:
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)." RETCODE, server[id].name, ip);
read_gm_account();
// send GM accounts to all char-servers
@ -1455,7 +1446,7 @@ int parse_fromchar(int fd) {
RFIFOSKIP(fd,2);
break;
case 0x2712: // request from char-server to authentify an account
case 0x2712: // request from char-server to authenticate an account
if (RFIFOREST(fd) < 19)
return 0;
{
@ -1466,8 +1457,9 @@ int parse_fromchar(int fd) {
auth_fifo[i].login_id1 == RFIFOL(fd,6) &&
auth_fifo[i].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18
auth_fifo[i].sex == RFIFOB(fd,14) &&
auth_fifo[i].ip == RFIFOL(fd,15) &&
!auth_fifo[i].delflag) {
auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) &&
!auth_fifo[i].delflag)
{
unsigned int k;
time_t connect_until_time = 0;
char email[40] = "";
@ -1475,7 +1467,6 @@ int parse_fromchar(int fd) {
auth_fifo[i].delflag = 1;
login_log("Char-server '%s': authentification of the account %d accepted (ip: %s)." RETCODE,
server[id].name, account_id, ip);
// printf("%d\n", i);
for(k = 0; k < auth_num; k++) {
if (auth_dat[k].account_id == account_id) {
strcpy(email, auth_dat[k].email);
@ -1521,44 +1512,37 @@ int parse_fromchar(int fd) {
RFIFOSKIP(fd,6);
break;
// we receive a e-mail creation of an account with a default e-mail (no answer)
case 0x2715:
case 0x2715: // request from char server to change e-email from default "a@a.com"
if (RFIFOREST(fd) < 46)
return 0;
{
char email[40];
acc = RFIFOL(fd,2); // speed up
memcpy(email, RFIFOP(fd,6), 40);
email[39] = '\0';
int acc = RFIFOL(fd,2);
memcpy(email, RFIFOP(fd,6), 40); email[39] = '\0';
remove_control_chars((unsigned char *)email);
//printf("parse_fromchar: an e-mail creation of an account with a default e-mail: server '%s', account: %d, e-mail: '%s'.\n", server[id].name, acc, RFIFOP(fd,6));
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)" RETCODE,
server[id].name, acc, ip);
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)" RETCODE, 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)." RETCODE,
server[id].name, acc, email, ip);
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)." RETCODE, server[id].name, acc, email, ip);
// Save
mmo_auth_sync();
break;
}
}
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)." RETCODE,
server[id].name, acc, ip);
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)." RETCODE, server[id].name, acc, ip);
}
}
RFIFOSKIP(fd,46);
break;
// We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server
case 0x2716:
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)
return 0;
//printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2));
for(i = 0; i < auth_num; i++) {
if (auth_dat[i].account_id == RFIFOL(fd,2)) {
login_log("Char-server '%s': e-mail of the account %d found (ip: %s)." RETCODE,
@ -1577,13 +1561,13 @@ int parse_fromchar(int fd) {
RFIFOSKIP(fd,6);
break;
case 0x2720: // To become GM request
case 0x2720: // Request to become a GM
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
{
unsigned char buf[10];
FILE *fp;
acc = RFIFOL(fd,4);
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;
@ -1638,7 +1622,7 @@ int parse_fromchar(int fd) {
return 0;
{
char actual_email[40], new_email[40];
acc = RFIFOL(fd,2);
int acc = RFIFOL(fd,2);
memcpy(actual_email, RFIFOP(fd,6), 40);
actual_email[39] = '\0';
remove_control_chars((unsigned char *)actual_email);
@ -1677,16 +1661,19 @@ int parse_fromchar(int fd) {
RFIFOSKIP(fd, 86);
break;
// Receiving of map-server via char-server a status change resquest (by Yor)
case 0x2724:
case 0x2724: // Receiving of map-server via char-server a status change resquest
if (RFIFOREST(fd) < 10)
return 0;
{
int acc, statut;
acc = RFIFOL(fd,2);
statut = RFIFOL(fd,6);
for(i = 0; i < auth_num; i++) {
if (auth_dat[i].account_id == acc) {
for(i = 0; i < auth_num && auth_dat[i].account_id != acc; i++);
if (i == auth_num) {
login_log("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s)." RETCODE,
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)." RETCODE,
server[id].name, acc, statut, ip);
@ -1707,22 +1694,17 @@ int parse_fromchar(int fd) {
} else
login_log("Char-server '%s': Error of Status change - actual status is already the good status (account: %d, status %d, ip: %s)." RETCODE,
server[id].name, acc, statut, ip);
break;
}
}
if (i == auth_num) {
login_log("Char-server '%s': Error of Status change (account: %d not found, suggested status %d, ip: %s)." RETCODE,
server[id].name, acc, statut, ip);
}
RFIFOSKIP(fd,10);
}
return 0;
case 0x2725: // Receiving of map-server via char-server a ban resquest (by Yor)
RFIFOSKIP(fd,10);
return 0;
}
case 0x2725: // Receiving of map-server via char-server a ban resquest
if (RFIFOREST(fd) < 18)
return 0;
{
acc = RFIFOL(fd,2);
int acc = RFIFOL(fd,2);
for(i = 0; i < auth_num; i++) {
if (auth_dat[i].account_id == acc) {
time_t timestamp;
@ -1779,17 +1761,16 @@ int parse_fromchar(int fd) {
login_log("Char-server '%s': Error of ban request (account: %d not found, ip: %s)." RETCODE,
server[id].name, acc, ip);
RFIFOSKIP(fd,18);
}
return 0;
}
case 0x2727: // Change of sex (sex is reversed)
if (RFIFOREST(fd) < 6)
return 0;
{
int sex;
acc = RFIFOL(fd,2);
int acc = RFIFOL(fd,2);
for(i = 0; i < auth_num; i++) {
// printf("%d,", auth_dat[i].account_id);
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)." RETCODE,
@ -1820,15 +1801,15 @@ int parse_fromchar(int fd) {
login_log("Char-server '%s': Error of sex change (account: %d not found, sex would be reversed, ip: %s)." RETCODE,
server[id].name, acc, ip);
RFIFOSKIP(fd,6);
}
return 0;
}
case 0x2728: // We receive account_reg2 from a char-server, and we send them to other map-servers.
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
{
int p;
acc = RFIFOL(fd,4);
int acc = RFIFOL(fd,4);
for(i = 0; i < auth_num; i++) {
if (auth_dat[i].account_id == acc) {
//unsigned char buf[rfifow(fd,2)+1];
@ -1868,10 +1849,11 @@ int parse_fromchar(int fd) {
RFIFOSKIP(fd,RFIFOW(fd,2));
break;
case 0x272a: // Receiving of map-server via char-server a unban resquest (by Yor)
case 0x272a: // Receiving of map-server via char-server a unban resquest
if (RFIFOREST(fd) < 6)
return 0;
{
int acc;
acc = RFIFOL(fd,2);
for(i = 0; i < auth_num; i++) {
if (auth_dat[i].account_id == acc) {
@ -1962,10 +1944,8 @@ int parse_fromchar(int fd) {
case 0x2736: // WAN IP update from char-server
if (RFIFOREST(fd) < 6)
return 0;
ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id,
(int)RFIFOB(fd,2),(int)RFIFOB(fd,3),
(int)RFIFOB(fd,4),(int)RFIFOB(fd,5));
server[id].ip = 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));
RFIFOSKIP(fd,6);
break;
@ -1975,37 +1955,6 @@ int parse_fromchar(int fd) {
RFIFOSKIP(fd,2);
break;
case 0x3000: //change sex for chrif_changesex()
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
{
unsigned int sex;
acc = RFIFOL(fd,4);
sex = RFIFOB(fd,8);
if (sex != 0 && sex != 1)
sex = 0;
for(i = 0; i < auth_num; i++) {
if (auth_dat[i].account_id == acc) {
unsigned char buf[16];
login_log("Char-server '%s': Sex change (account: %d, new sex %c, ip: %s)." RETCODE,
server[id].name, acc, (sex == 2) ? 'S' : (sex ? 'M' : 'F'), ip);
auth_fifo[i].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentification)
auth_dat[i].sex = sex;
WBUFW(buf,0) = 0x2723;
WBUFL(buf,2) = acc;
WBUFB(buf,6) = sex;
charif_sendallwos(-1, buf, 7);
break;
}
}
if (i == auth_num) {
login_log("Char-server '%s': Error of Sex change (account: %d not found, suggested sex %c, ip: %s)." RETCODE,
server[id].name, acc, (sex == 2) ? 'S' : (sex ? 'M' : 'F'), ip);
}
RFIFOSKIP(fd,RFIFOW(fd,2));
}
return 0;
default:
{
FILE *logfp;
@ -2047,9 +1996,8 @@ int parse_fromchar(int fd) {
fclose(logfp);
}
}
ShowWarning("parse_fromchar: Unknown packet 0x%x (from a char-server)! -> disconnection.\n", RFIFOW(fd,0));
ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", RFIFOW(fd,0));
session[fd]->eof = 1;
ShowStatus("Char-server has been disconnected (unknown packet).\n");
return 0;
}
}
@ -2060,14 +2008,15 @@ int parse_fromchar(int fd) {
//---------------------------------------
// Packet parsing for administation login
//---------------------------------------
int parse_admin(int fd) {
int parse_admin(int fd)
{
unsigned int i, j;
unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
uint32 ipl = session[fd]->client_addr;
char* account_name;
char ip[16];
RFIFOHEAD(fd);
sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
ip2str(ipl, ip);
if (session[fd]->eof) {
do_close(fd);
@ -2108,8 +2057,6 @@ int parse_admin(int fd) {
return 0;
{
int st, ed, len;
//int id[auth_num];
//int *id=(int *)aCalloc(auth_num, sizeof(int));
CREATE_BUFFER(id, int, auth_num);
st = RFIFOL(fd,2);
ed = RFIFOL(fd,6);
@ -2336,8 +2283,8 @@ int parse_admin(int fd) {
server_num = 0;
for(i = 0; i < MAX_SERVERS; i++) {
if (server_fd[i] >= 0) {
WFIFOL(fd,4+server_num*32) = server[i].ip;
WFIFOW(fd,4+server_num*32+4) = server[i].port;
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;
@ -3027,12 +2974,12 @@ int parse_admin(int fd) {
//--------------------------------------------
// Test to know if an IP come from LAN or WAN.
//--------------------------------------------
int lan_subnetcheck(long *p) {
int lan_subnetcheck(uint32 ip)
{
int i;
for(i=0; i<subnet_count; i++) {
if(subnet[i].subnet == (*p & subnet[i].mask)) {
for(i = 0; i < subnet_count; i++) {
if(subnet[i].subnet == (ip & subnet[i].mask)) {
return subnet[i].char_ip;
}
}
@ -3043,18 +2990,16 @@ int lan_subnetcheck(long *p) {
//----------------------------------------------------------------------------------------
// Default packet parsing (normal players or administation/char-server connexion requests)
//----------------------------------------------------------------------------------------
int parse_login(int fd) {
int parse_login(int fd)
{
struct mmo_account account;
int result, j;
unsigned int i;
unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
uint32 ipl = session[fd]->client_addr;
char ip[16];
long subnet_char_ip;
RFIFOHEAD(fd);
sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
ip2str(ipl, ip);
memset(&account, 0, sizeof(account));
@ -3094,6 +3039,17 @@ int parse_login(int fd) {
{
int packet_len = RFIFOREST(fd);
//Perform ip-ban check
if (!check_ip(ipl)) {
login_log("Connection refused: IP isn't authorised (deny/allow, ip: %s)." RETCODE, ip);
WFIFOHEAD(fd, 23);
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = 3; // 3 = Rejected from Server
WFIFOSET(fd,23);
RFIFOSKIP(fd,packet_len);
break;
}
switch(RFIFOW(fd, 0)){
case 0x64:
if(packet_len < 55)
@ -3109,9 +3065,9 @@ int parse_login(int fd) {
break;
}
account.version = RFIFOL(fd, 2); //for exe version check [Sirius]
account.version = RFIFOL(fd, 2);
if (!account.version) account.version = 1; //Force some version...
memcpy(account.userid,RFIFOP(fd,6),NAME_LENGTH);
memcpy(account.userid,RFIFOP(fd, 6),NAME_LENGTH);
account.userid[23] = '\0';
remove_control_chars((unsigned char *)account.userid);
if (RFIFOW(fd,0) != 0x01dd) {
@ -3132,18 +3088,8 @@ int parse_login(int fd) {
account.passwdenc = 0;
#endif
if (!check_ip(session[fd]->client_addr.sin_addr.s_addr)) {
login_log("Connection refused: IP isn't authorised (deny/allow, ip: %s)." RETCODE, ip);
WFIFOHEAD(fd, 23);
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = 3; // 3 = Rejected from Server
WFIFOSET(fd,23);
RFIFOSKIP(fd,packet_len);
break;
}
result = mmo_auth(&account, fd);
if (result == -1) {
if (result == -1) { // auth success
int gm_level = isGM(account.account_id);
if (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)." RETCODE,
@ -3157,16 +3103,15 @@ int parse_login(int fd) {
ShowInfo("Connection of the GM (level:%d) account '%s' accepted.\n", gm_level, account.userid);
else
ShowInfo("Connection of the account '%s' accepted.\n", account.userid);
server_num = 0;
WFIFOHEAD(fd, 47+32*MAX_SERVERS);
for(i = 0; i < MAX_SERVERS; i++) {
if (server_fd[i] >= 0) {
// Andvanced subnet check [LuzZza]
if((subnet_char_ip = lan_subnetcheck((long*)p)))
WFIFOL(fd,47+server_num*32) = subnet_char_ip;
else
WFIFOL(fd,47+server_num*32) = server[i].ip;
WFIFOW(fd,47+server_num*32+4) = server[i].port;
// Advanced subnet check [LuzZza]
uint32 subnet_char_ip = lan_subnetcheck(ipl);
WFIFOL(fd,47+server_num*32) = (subnet_char_ip) ? htonl(subnet_char_ip) : htonl(server[i].ip);
WFIFOW(fd,47+server_num*32+4) = server[i].port; // /!\ must be sent in intel host byte order /!\ (client bug)
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;
@ -3174,8 +3119,7 @@ int parse_login(int fd) {
server_num++;
}
}
// if at least 1 char-server
if (server_num > 0) {
if (server_num > 0) { // if at least 1 char-server
WFIFOW(fd,0) = 0x69;
WFIFOW(fd,2) = 47+32*server_num;
WFIFOL(fd,4) = account.login_id1;
@ -3192,10 +3136,9 @@ int parse_login(int fd) {
auth_fifo[auth_fifo_pos].login_id2 = account.login_id2;
auth_fifo[auth_fifo_pos].sex = account.sex;
auth_fifo[auth_fifo_pos].delflag = 0;
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr;
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
auth_fifo_pos++;
// if no char-server, don't send void list of servers, just disconnect the player with proper message
} else {
} else { // if no char-server, don't send void list of servers, just disconnect the player with proper message
login_log("Connection refused: there is no char-server online (account: %s, ip: %s)." RETCODE,
account.userid, ip);
WFIFOW(fd,0) = 0x81;
@ -3203,29 +3146,25 @@ int parse_login(int fd) {
WFIFOSET(fd,3);
}
}
} else {
} else { // auth failed
WFIFOHEAD(fd, 23);
memset(WFIFOP(fd,0), '\0', 23);
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = result;
if (result == 6) { // 6 = Your are Prohibited to log in until %s
char tmpstr[20];
time_t ban_until_time;
i = search_account_index(account.userid);
if (i != -1) {
if (auth_dat[i].ban_until_time != 0) { // if account is banned, we send ban timestamp
char tmpstr[256];
strftime(tmpstr, 20, date_format, localtime(&auth_dat[i].ban_until_time));
tmpstr[19] = '\0';
memcpy(WFIFOP(fd,3), tmpstr, 20);
} else { // we send error message
memcpy(WFIFOP(fd,3), auth_dat[i].error_message, 20);
}
}
ban_until_time = (i) ? auth_dat[i].ban_until_time : 0;
strftime(tmpstr, 20, date_format, localtime(&ban_until_time)); tmpstr[19] = '\0';
strncpy(WFIFOP(fd,3), tmpstr, 20); // ban timestamp goes here
}
WFIFOSET(fd,23);
}
RFIFOSKIP(fd,packet_len);
break;
}
case 0x01db: // Sending request of the coding key
case 0x791a: // Sending request of the coding key (administration packet)
{
@ -3246,6 +3185,7 @@ int parse_login(int fd) {
ld->md5keylen = rand() % 4 + 12;
for(i = 0; i < ld->md5keylen; i++)
ld->md5key[i] = rand() % 255 + 1;
RFIFOSKIP(fd,2);
WFIFOHEAD(fd, 4 + ld->md5keylen);
WFIFOW(fd,0) = 0x01dc;
@ -3259,29 +3199,29 @@ int parse_login(int fd) {
if (RFIFOREST(fd) < 86)
return 0;
{
int GM_value, len;
int len;
char* server_name;
uint32 server_ip;
uint16 server_port;
WFIFOHEAD(fd, 3);
memcpy(account.userid,RFIFOP(fd,2),NAME_LENGTH);
account.userid[23] = '\0';
remove_control_chars((unsigned char *)account.userid);
memcpy(account.passwd, RFIFOP(fd,26), NAME_LENGTH);
account.passwd[23] = '\0';
remove_control_chars((unsigned char *)account.passwd);
memcpy(account.userid,RFIFOP(fd,2),NAME_LENGTH); account.userid[23] = '\0'; remove_control_chars((unsigned char *)account.userid);
memcpy(account.passwd, RFIFOP(fd,26), NAME_LENGTH); account.passwd[23] = '\0'; remove_control_chars((unsigned char *)account.passwd);
account.passwdenc = 0;
server_name = (char*)RFIFOP(fd,60);
server_name[20] = '\0';
remove_control_chars((unsigned char *)server_name);
server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0'; remove_control_chars((unsigned char *)server_name);
server_ip = ntohl(RFIFOL(fd, 54));
server_port = ntohs(RFIFOW(fd, 58));
login_log("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)" RETCODE,
server_name, RFIFOB(fd,54), RFIFOB(fd,55), RFIFOB(fd,56), RFIFOB(fd,57), RFIFOW(fd,58), ip);
server_name, CONVIP(server_ip), server_port, ip);
result = mmo_auth(&account, fd);
if (result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1) {
login_log("Connection of the char-server '%s' accepted (account: %s, pass: %s, ip: %s)" RETCODE,
server_name, account.userid, account.passwd, ip);
ShowStatus("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 = RFIFOL(fd,54);
server[account.account_id].port = RFIFOW(fd,58);
server[account.account_id].ip = ntohl(RFIFOL(fd,54));
server[account.account_id].port = ntohs(RFIFOW(fd,58));
memcpy(server[account.account_id].name, server_name, 20);
server[account.account_id].users = 0;
server[account.account_id].maintenance = RFIFOW(fd,82);
@ -3292,18 +3232,24 @@ int parse_login(int fd) {
WFIFOSET(fd,3);
session[fd]->func_parse = parse_fromchar;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
//TODO: why not use send_GM_accounts(fd)?
// send GM account to char-server
len = 4;
WFIFOW(fd,0) = 0x2732;
for(i = 0; i < auth_num; i++)
for(i = 0; i < auth_num; i++) {
// send only existing accounts. We can not create a GM account when server is online.
int GM_value;
if ((GM_value = isGM(auth_dat[i].account_id)) > 0) {
WFIFOL(fd,len) = auth_dat[i].account_id;
WFIFOB(fd,len+4) = (unsigned char)GM_value;
len += 5;
}
}
WFIFOW(fd,2) = len;
WFIFOSET(fd,len);
// /TODO
} else {
if (server_fd[account.account_id] != -1) {
ShowNotice("Connection of the char-server '%s' REFUSED - already connected (account: %ld-%s, pass: %s, ip: %s)\n",
@ -3315,7 +3261,7 @@ int parse_login(int fd) {
login_log("Connexion of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s)" RETCODE,
server_name, account.userid, account.passwd, ip);
}
WFIFOHEAD(fd, 3);
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2711;
WFIFOB(fd,2) = 3;
WFIFOSET(fd,3);
@ -3324,7 +3270,7 @@ int parse_login(int fd) {
RFIFOSKIP(fd,86);
return 0;
case 0x7530: // Request of the server version
case 0x7530: // Server version information request
login_log("Sending of the server version (ip: %s)" RETCODE, ip);
WFIFOHEAD(fd, 10);
WFIFOW(fd,0) = 0x7531;
@ -3349,7 +3295,7 @@ int parse_login(int fd) {
return 0;
WFIFOW(fd,0) = 0x7919;
WFIFOB(fd,2) = 1;
if (!check_ladminip(session[fd]->client_addr.sin_addr.s_addr)) {
if (!check_ladminip(session[fd]->client_addr)) {
login_log("'ladmin'-login: Connection in administration mode refused: IP isn't authorised (ladmin_allow, ip: %s)." RETCODE, ip);
} else {
struct login_session_data *ld = (struct login_session_data*)session[fd]->session_data;
@ -3437,7 +3383,7 @@ int parse_login(int fd) {
fclose(logfp);
}
}
login_log("End of connection, unknown packet (ip: %s)" RETCODE, ip);
login_log("Abnormal end of connection (ip: %s): Unknown packet 0x%x " RETCODE, ip, RFIFOW(fd,0));
session[fd]->eof = 1;
return 0;
}
@ -3449,7 +3395,7 @@ int parse_login(int fd) {
//-----------------------
// Console Command Parser [Wizputer]
//-----------------------
int parse_console(char *buf)
int parse_console(char*buf)
{
char command[256];
@ -3545,9 +3491,9 @@ int login_lan_config_read(const char *lancfgName)
if(strcmpi(w1, "subnet") == 0) {
subnet[subnet_count].mask = inet_addr(w2);
subnet[subnet_count].char_ip = inet_addr(w3);
subnet[subnet_count].map_ip = inet_addr(w4);
subnet[subnet_count].mask = ntohl(inet_addr(w2));
subnet[subnet_count].char_ip = ntohl(inet_addr(w3));
subnet[subnet_count].map_ip = ntohl(inet_addr(w4));
subnet[subnet_count].subnet = subnet[subnet_count].char_ip&subnet[subnet_count].mask;
if (subnet[subnet_count].subnet != (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);
@ -3587,7 +3533,6 @@ int login_config_read(const char* cfgName)
if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
continue;
//TODO: unindent
remove_control_chars((unsigned char *)w1);
remove_control_chars((unsigned char *)w2);
@ -3598,7 +3543,8 @@ int login_config_read(const char* cfgName)
} else if(strcmpi(w1,"console_silent")==0){
ShowInfo("Console Silent Setting: %d\n", atoi(w2));
msg_silent = atoi(w2);
} else if (strcmpi(w1, "admin_state") == 0) {
}
else if (strcmpi(w1, "admin_state") == 0) {
admin_state = config_switch(w2);
} else if (strcmpi(w1, "admin_pass") == 0) {
memset(admin_pass, 0, sizeof(admin_pass));
@ -3634,9 +3580,8 @@ int login_config_read(const char* cfgName)
gm_pass[sizeof(gm_pass)-1] = '\0';
} else if (strcmpi(w1, "level_new_gm") == 0) {
level_new_gm = atoi(w2);
} else if (strcmpi(w1, "new_account") == 0) {
new_account_flag = config_switch(w2);
} else if (strcmpi(w1, "bind_ip") == 0) {
}
else if (strcmpi(w1, "bind_ip") == 0) {
char ip_str[16];
login_ip = host2ip(w2);
if (login_ip)
@ -3653,14 +3598,12 @@ int login_config_read(const char* cfgName)
GM_account_filename[sizeof(GM_account_filename)-1] = '\0';
} else if (strcmpi(w1, "gm_account_filename_check_timer") == 0) {
gm_account_filename_check_timer = atoi(w2);
} else if (strcmpi(w1, "use_MD5_passwords") == 0) {
use_md5_passwds = config_switch(w2);
} else if (strcmpi(w1, "log_login") == 0) {
log_login = 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, "log_login") == 0) {
log_login = config_switch(w2);
} 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));
@ -3673,10 +3616,6 @@ int login_config_read(const char* cfgName)
display_parse_admin = config_switch(w2);
} else if (strcmpi(w1, "display_parse_fromchar") == 0) {
display_parse_fromchar = config_switch(w2); // 0: no, 1: yes (without packet 0x2714), 2: all packets
} else if (!strcmpi(w1, "date_format")) {
strncpy(date_format, w2, sizeof(date_format));
} else if (strcmpi(w1, "min_level_to_connect") == 0) {
min_level_to_connect = atoi(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) {
@ -3737,10 +3676,18 @@ int login_config_read(const char* cfgName)
access_deny[access_denynum * ACO_STRSIZE - 1] = '\0';
}
}
} else if (strcmpi(w1, "new_account") == 0) {
new_account_flag = config_switch(w2);
} else if(strcmpi(w1, "check_client_version") == 0) {
check_client_version = config_switch(w2);
} else if(strcmpi(w1, "client_version_to_connect") == 0) {
client_version_to_connect = atoi(w2);
} else if (strcmpi(w1, "use_MD5_passwords") == 0) {
use_md5_passwds = config_switch(w2);
} else if (strcmpi(w1, "min_level_to_connect") == 0) {
min_level_to_connect = atoi(w2);
} else if (!strcmpi(w1, "date_format")) {
strncpy(date_format, w2, sizeof(date_format));
} else if (strcmpi(w1, "console") == 0) {
console = config_switch(w2);
} else if (strcmpi(w1, "allowed_regs") == 0) { //account flood protection system

View File

@ -40,7 +40,7 @@
struct Login_Config {
in_addr_t login_ip; // the address to bind to
uint32 login_ip; // the address to bind to
unsigned short login_port; // the port to bind to
bool log_login; // whether to log login server actions or not
char date_format[32]; // date format used in messages
@ -71,17 +71,17 @@ struct mmo_char_server server[MAX_SERVERS]; // char server data
// Advanced subnet check [LuzZza]
struct _subnet {
long subnet;
long mask;
long char_ip;
long map_ip;
uint32 subnet;
uint32 mask;
uint32 char_ip;
uint32 map_ip;
} subnet[16];
int subnet_count = 0;
struct gm_account* gm_account_db = NULL;
int GM_num = 0; // number of gm accounts
unsigned int GM_num = 0; // number of gm accounts
//Account registration flood protection [Kevin]
int allowed_regs = 1;
@ -118,7 +118,9 @@ char login_db_level[256] = "level";
#define AUTH_FIFO_SIZE 256
struct {
int account_id,login_id1,login_id2;
int ip,sex,delflag;
uint32 ip;
char sex;
bool delflag;
} auth_fifo[AUTH_FIFO_SIZE];
int auth_fifo_pos = 0;
@ -235,12 +237,13 @@ void read_gm_account(void)
//-----------------------------------------------------
void send_GM_accounts(int fd)
{
int i;
unsigned int i;
unsigned char buf[32767];
int len;
if(!login_config.login_gm_read)
return;
len = 4;
WBUFW(buf,0) = 0x2732;
for(i = 0; i < GM_num; i++)
@ -254,6 +257,7 @@ void send_GM_accounts(int fd)
break;
}
}
WBUFW(buf,2) = len;
if (fd == -1)
charif_sendallwos(-1, buf, len);
@ -497,20 +501,20 @@ int mmo_auth_new(struct mmo_account* account, char sex)
return 0;
}
// Send to char
//--------------------------------------------------------------------
// Packet send to all char-servers, except one (wos: without our self)
//--------------------------------------------------------------------
int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len)
{
int i, c;
int fd;
int i, c, fd;
c = 0;
for(i = 0; i < MAX_SERVERS; i++) {
for(i = 0, c = 0; i < MAX_SERVERS; i++) {
if ((fd = server_fd[i]) > 0 && fd != sfd) {
WFIFOHEAD(fd,len);
WFIFOHEAD(fd, len);
if (WFIFOSPACE(fd) < len) //Increase buffer size.
realloc_writefifo(fd, len);
memcpy(WFIFOP(fd,0), buf, len);
WFIFOSET(fd,len);
WFIFOSET(fd, len);
c++;
}
}
@ -532,8 +536,9 @@ int mmo_auth(struct mmo_account* account, int fd)
char md5str[64], md5bin[32];
char ip[16];
unsigned char* sin_addr = (unsigned char *)&session[fd]->client_addr.sin_addr.s_addr;
sprintf(ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
uint32 ipl = session[fd]->client_addr;
uint8* sin_addr = (uint8*)&ipl;
sprintf(ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]);
// DNS Blacklist check
if(login_config.use_dnsbl)
@ -543,7 +548,7 @@ int mmo_auth(struct mmo_account* account, int fd)
char *dnsbl_serv;
bool matched = false;
sprintf(r_ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]);
sprintf(r_ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
for (dnsbl_serv = strtok(login_config.dnsbl_servs,","); dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,","))
{
@ -720,9 +725,9 @@ int mmo_auth(struct mmo_account* account, int fd)
if (login_config.online_check) {
struct online_login_data* data = idb_get(online_db,account->account_id);
unsigned char buf[8];
if (data && data->char_server > -1) {
//Request char servers to kick this account out. [Skotlex]
unsigned char buf[8];
ShowNotice("User [%s] is already online - Rejected.\n",account->userid);
WBUFW(buf,0) = 0x2734;
WBUFL(buf,2) = account->account_id;
@ -764,19 +769,18 @@ static int online_db_setoffline(DBKey key, void* data, va_list ap)
return 0;
}
//-----------------------------------------------------
// char-server packet parse
//-----------------------------------------------------
//--------------------------------
// Packet parsing for char-servers
//--------------------------------
int parse_fromchar(int fd)
{
int i, id;
unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr.s_addr;
unsigned long ipl = session[fd]->client_addr.sin_addr.s_addr;
uint32 ipl = session[fd]->client_addr;
char ip[16];
RFIFOHEAD(fd);
sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
ip2str(ipl, ip);
for(id = 0; id < MAX_SERVERS; id++)
if (server_fd[id] == fd)
@ -802,14 +806,14 @@ int parse_fromchar(int fd)
return 0;
}
while(RFIFOREST(fd) >= 2) {
// printf("char_parse: %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0));
while (RFIFOREST(fd) >= 2) {
switch (RFIFOW(fd,0)) {
case 0x2709:
case 0x2709: // request from map-server via char-server to reload GM accounts
if (login_config.log_login)
{
sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, (unsigned int)ntohl(ipl),server[id].name);
sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, ipl, server[id].name);
if (mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@ -821,7 +825,7 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,2);
break;
case 0x2712:
case 0x2712: // request from char-server to authenticate an account
if (RFIFOREST(fd) < 19)
return 0;
{
@ -833,7 +837,7 @@ int parse_fromchar(int fd)
auth_fifo[i].login_id1 == RFIFOL(fd,6) &&
auth_fifo[i].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18
auth_fifo[i].sex == RFIFOB(fd,14) &&
auth_fifo[i].ip == RFIFOL(fd,15) &&
auth_fifo[i].ip == ntohl(RFIFOL(fd,15)) &&
!auth_fifo[i].delflag)
{
auth_fifo[i].delflag = 1;
@ -869,9 +873,10 @@ int parse_fromchar(int fd)
WFIFOB(fd,6) = 1;
WFIFOSET(fd,51);
}
}
RFIFOSKIP(fd,19);
break;
}
case 0x2714:
if (RFIFOREST(fd) < 6)
@ -897,8 +902,7 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,6);
break;
// We receive an e-mail/limited time request, because a player comes back from a map-server to the char-server
case 0x2716:
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)
return 0;
{
@ -929,10 +933,8 @@ int parse_fromchar(int fd)
RFIFOSKIP(fd,6);
break;
case 0x2720: // GM
if (RFIFOREST(fd) < 4)
return 0;
if (RFIFOREST(fd) < RFIFOW(fd,2))
case 0x2720: // Request to become a GM (TXT only!)
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
//oldacc = RFIFOL(fd,4);
ShowWarning("change GM isn't supported in this login server version.\n");
@ -995,7 +997,7 @@ int parse_fromchar(int fd)
break;
}
case 0x2724: // Receiving of map-server via char-server a status change resquest (by Yor)
case 0x2724: // Receiving of map-server via char-server a status change resquest
if (RFIFOREST(fd) < 10)
return 0;
{
@ -1029,7 +1031,7 @@ int parse_fromchar(int fd)
break;
}
case 0x2725: // Receiving of map-server via char-server a ban resquest (by Yor)
case 0x2725: // Receiving of map-server via char-server a ban resquest
if (RFIFOREST(fd) < 18)
return 0;
{
@ -1084,7 +1086,7 @@ int parse_fromchar(int fd)
break;
}
case 0x2727:
case 0x2727: // Change of sex (sex is reversed)
if (RFIFOREST(fd) < 6)
return 0;
{
@ -1168,10 +1170,9 @@ int parse_fromchar(int fd)
if (buf) aFree(buf);
}
RFIFOSKIP(fd,RFIFOW(fd,2));
//printf("login: save account_reg (from char)\n");
break;
case 0x272a: // Receiving of map-server via char-server a unban resquest (by Yor)
case 0x272a: // Receiving of map-server via char-server a unban resquest
if (RFIFOREST(fd) < 6)
return 0;
{
@ -1209,6 +1210,7 @@ int parse_fromchar(int fd)
remove_online_user(RFIFOL(fd,2));
RFIFOSKIP(fd,6);
break;
case 0x272d: // Receive list of all online accounts. [Skotlex]
if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
return 0;
@ -1270,10 +1272,8 @@ int parse_fromchar(int fd)
case 0x2736: // WAN IP update from char-server
if (RFIFOREST(fd) < 6)
return 0;
ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id,
(int)RFIFOB(fd,2),(int)RFIFOB(fd,3),
(int)RFIFOB(fd,4),(int)RFIFOB(fd,5));
server[id].ip = 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));
RFIFOSKIP(fd,6);
break;
@ -1284,7 +1284,7 @@ int parse_fromchar(int fd)
break;
default:
ShowError("login: unknown packet %x! (from char).\n", RFIFOW(fd,0));
ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", RFIFOW(fd,0));
session[fd]->eof = 1;
return 0;
}
@ -1297,12 +1297,12 @@ int parse_fromchar(int fd)
//--------------------------------------------
// Test to know if an IP come from LAN or WAN.
//--------------------------------------------
int lan_subnetcheck(long p)
int lan_subnetcheck(uint32 ip)
{
int i;
for(i=0; i<subnet_count; i++) {
if(subnet[i].subnet == (p & subnet[i].mask)) {
for(i = 0; i < subnet_count; i++) {
if(subnet[i].subnet == (ip & subnet[i].mask)) {
return subnet[i].char_ip;
}
}
@ -1310,14 +1310,11 @@ int lan_subnetcheck(long p)
return 0;
}
int login_ip_ban_check(unsigned char *p, unsigned long ipl)
int login_ip_ban_check(uint32 ip)
{
//ip ban
//p[0], p[1], p[2], p[3]
//request DB connection
//check
char* p = (char*)&ip;
sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'",
p[0], p[0], p[1], p[0], p[1], p[2], p[0], p[1], p[2], p[3]);
p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]);
if (mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@ -1338,11 +1335,11 @@ int login_ip_ban_check(unsigned char *p, unsigned long ipl)
}
// ip ban ok.
ShowInfo("Packet from banned ip : %d.%d.%d.%d\n" RETCODE, p[0], p[1], p[2], p[3]);
ShowInfo("Packet from banned ip : %d.%d.%d.%d\n" RETCODE, CONVIP(ip));
if (login_config.log_login)
{
sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', 'unknown','-3', 'ip banned')", loginlog_db, (unsigned int)ntohl(ipl));
sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', 'unknown','-3', 'ip banned')", loginlog_db, ip);
// query
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
@ -1360,16 +1357,13 @@ int parse_login(int fd)
{
char t_uid[100];
struct mmo_account account;
long subnet_char_ip;
int packet_len;
int result, i;
unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr.s_addr;
unsigned long ipl = session[fd]->client_addr.sin_addr.s_addr;
uint32 ipl = session[fd]->client_addr;
char ip[16];
RFIFOHEAD(fd);
sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
ip2str(ipl, ip);
memset(&account, 0, sizeof(account));
@ -1381,9 +1375,9 @@ int parse_login(int fd)
return 0;
}
while(RFIFOREST(fd)>=2 && !session[fd]->eof){
while(RFIFOREST(fd) >= 2) {
switch(RFIFOW(fd,0)){
switch(RFIFOW(fd,0)) {
case 0x200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
if (RFIFOREST(fd) < 26)
return 0;
@ -1399,18 +1393,22 @@ int parse_login(int fd)
case 0x277: // New login packet
case 0x64: // request client login
case 0x01dd: // request client login with encrypt
packet_len = RFIFOREST(fd);
//Perform ip-ban check ONLY on login packets
if (login_config.ipban && login_ip_ban_check(p,ipl))
{
int packet_len = RFIFOREST(fd);
//Perform ip-ban check
if (login_config.ipban && login_ip_ban_check(ipl))
{
WFIFOHEAD(fd, 23);
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = 3; // 3 = Rejected from Server
WFIFOSET(fd,23);
RFIFOSKIP(fd,packet_len);
session[fd]->eof = 1;
break;
}
switch(RFIFOW(fd,0)){
switch(RFIFOW(fd, 0)){
case 0x64:
if(packet_len < 55)
return 0;
@ -1432,7 +1430,6 @@ int parse_login(int fd)
memcpy(account.passwd,RFIFOP(fd, 30),NAME_LENGTH);
account.passwd[23] = '\0';
// ShowDebug("client connection request %s from %d.%d.%d.%d\n", RFIFOP(fd, 6), p[0], p[1], p[2], p[3]);
#ifdef PASSWORDENC
account.passwdenc= (RFIFOW(fd,0)!=0x01dd)?0:PASSWORDENC;
#else
@ -1441,7 +1438,7 @@ int parse_login(int fd)
result=mmo_auth(&account, fd);
jstrescapecpy(t_uid,account.userid);
if(result==-1){
if(result==-1) { // auth success
if (login_config.min_level_to_connect > account.level) {
WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x81;
@ -1449,8 +1446,8 @@ int parse_login(int fd)
WFIFOSET(fd,3);
} else {
WFIFOHEAD(fd,47+32*MAX_SERVERS);
if (p[0] != 127 && login_config.log_login) {
sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, (unsigned int)ntohl(ipl), t_uid);
if (login_config.log_login) {
sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, t_uid);
//query
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
@ -1461,15 +1458,14 @@ int parse_login(int fd)
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);
server_num=0;
server_num = 0;
for(i = 0; i < MAX_SERVERS; i++) {
if (server_fd[i] >= 0) {
// Advanced subnet check [LuzZza]
if((subnet_char_ip = lan_subnetcheck(ipl)))
WFIFOL(fd,47+server_num*32) = subnet_char_ip;
else
WFIFOL(fd,47+server_num*32) = server[i].ip;
WFIFOW(fd,47+server_num*32+4) = server[i].port;
uint32 subnet_char_ip = lan_subnetcheck(ipl);
WFIFOL(fd,47+server_num*32) = (subnet_char_ip) ? htonl(subnet_char_ip) : htonl(server[i].ip);
WFIFOW(fd,47+server_num*32+4) = server[i].port; // /!\ must be sent in intel host byte order /!\ (client bug)
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;
@ -1477,34 +1473,33 @@ int parse_login(int fd)
server_num++;
}
}
// if at least 1 char-server
if (server_num > 0) {
WFIFOW(fd,0)=0x69;
WFIFOW(fd,2)=47+32*server_num;
WFIFOL(fd,4)=account.login_id1;
WFIFOL(fd,8)=account.account_id;
WFIFOL(fd,12)=account.login_id2;
WFIFOL(fd,16)=0;
//memcpy(WFIFOP(fd,20),account.lastlogin,24);
WFIFOB(fd,46)=account.sex;
if (server_num > 0) { // if at least 1 char-server
WFIFOW(fd,0) = 0x69;
WFIFOW(fd,2) = 47+32*server_num;
WFIFOL(fd,4) = account.login_id1;
WFIFOL(fd,8) = account.account_id;
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)
WFIFOB(fd,46) = account.sex;
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;
auth_fifo[auth_fifo_pos].login_id1=account.login_id1;
auth_fifo[auth_fifo_pos].login_id2=account.login_id2;
auth_fifo[auth_fifo_pos].sex=account.sex;
auth_fifo[auth_fifo_pos].delflag=0;
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr;
if (auth_fifo_pos >= AUTH_FIFO_SIZE)
auth_fifo_pos = 0;
auth_fifo[auth_fifo_pos].account_id = account.account_id;
auth_fifo[auth_fifo_pos].login_id1 = account.login_id1;
auth_fifo[auth_fifo_pos].login_id2 = account.login_id2;
auth_fifo[auth_fifo_pos].sex = account.sex;
auth_fifo[auth_fifo_pos].delflag = 0;
auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr;
auth_fifo_pos++;
} else {
} else { // if no char-server, don't send void list of servers, just disconnect the player with proper message
WFIFOW(fd,0) = 0x81;
WFIFOB(fd,2) = 1; // 01 = Server closed
WFIFOSET(fd,3);
}
}
} else {
WFIFOHEAD(fd,23);
} else { // auth failed
WFIFOHEAD(fd, 23);
if (login_config.log_login)
{
const char* error;
@ -1536,7 +1531,7 @@ int parse_login(int fd)
default : error = "Unknown Error."; break;
}
sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d','login failed : %s')", loginlog_db, (unsigned int)ntohl(ipl), t_uid, result, error);
sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d','login failed : %s')", loginlog_db, ipl, t_uid, result, error);
//query
if(mysql_query(&mysql_handle, tmpsql)) {
@ -1547,7 +1542,7 @@ int parse_login(int fd)
if ((result == 1) && login_config.dynamic_pass_failure_ban && login_config.log_login) { // failed password
sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%u' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
loginlog_db,(unsigned int)ntohl(ipl), login_config.dynamic_pass_failure_ban_interval); //how many times filed account? in one ip.
loginlog_db, ipl, login_config.dynamic_pass_failure_ban_interval); //how many times filed account? in one ip.
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@ -1557,7 +1552,8 @@ int parse_login(int fd)
sql_row = sql_res?mysql_fetch_row(sql_res):NULL; //row fetching
if (sql_row && (unsigned int)atoi(sql_row[0]) >= login_config.dynamic_pass_failure_ban_limit ) {
sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", p[0], p[1], p[2], login_config.dynamic_pass_failure_ban_duration, t_uid);
uint8* p = (uint8*)&ipl;
sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", (uint8)p[3], (uint8)p[2], (uint8)p[1], login_config.dynamic_pass_failure_ban_duration, t_uid);
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@ -1566,7 +1562,8 @@ int parse_login(int fd)
if(sql_res) mysql_free_result(sql_res);
}
else if (result == -2){ //dynamic banned - add ip to ban list.
sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", p[0], p[1], p[2], t_uid);
uint8* p = (uint8*)&ipl;
sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", (uint8)p[3], (uint8)p[2], (uint8)p[1], t_uid);
if(mysql_query(&mysql_handle, tmpsql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
@ -1583,21 +1580,24 @@ int parse_login(int fd)
}
sql_res = mysql_store_result(&mysql_handle) ;
sql_row = sql_res?mysql_fetch_row(sql_res):NULL;
//cannot connect login failed
memset(WFIFOP(fd,0),'\0',23);
WFIFOW(fd,0)=0x6a;
WFIFOB(fd,2)=result;
memset(WFIFOP(fd,0), '\0', 23);
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = result;
if (result == 6) { // 6 = Your are Prohibited to log in until %s
char tmpstr[20];
time_t ban_until_time = (sql_row) ? atol(sql_row[0]) : 0;
strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time));
tmpstr[19] = '\0';
strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time)); tmpstr[19] = '\0';
strncpy(WFIFOP(fd,3), tmpstr, 20); // ban timestamp goes here
}
WFIFOSET(fd,23);
if (sql_res) mysql_free_result(sql_res);
}
RFIFOSKIP(fd,packet_len);
break;
}
case 0x01db: // request password key
if (session[fd]->session_data) {
@ -1606,41 +1606,39 @@ int parse_login(int fd)
return 0;
}
{
WFIFOHEAD(fd,4+md5keylen);
WFIFOW(fd,0)=0x01dc;
WFIFOW(fd,2)=4+md5keylen;
memcpy(WFIFOP(fd,4),md5key,md5keylen);
WFIFOSET(fd,WFIFOW(fd,2));
RFIFOSKIP(fd,2);
WFIFOHEAD(fd, 4 + md5keylen);
WFIFOW(fd,0) = 0x01dc;
WFIFOW(fd,2) = 4 + md5keylen;
memcpy(WFIFOP(fd,4), md5key, md5keylen);
WFIFOSET(fd,WFIFOW(fd,2));
}
break;
case 0x2710: // request Char-server connection
if(RFIFOREST(fd)<86)
case 0x2710: // Connection request of a char-server
if (RFIFOREST(fd) < 86)
return 0;
{
char* server_name;
uint32 server_ip;
uint16 server_port;
WFIFOHEAD(fd, 3);
memcpy(account.userid,RFIFOP(fd, 2),NAME_LENGTH);
account.userid[23] = '\0';
memcpy(account.passwd,RFIFOP(fd, 26),NAME_LENGTH);
account.passwd[23] = '\0';
memcpy(account.userid,RFIFOP(fd, 2),NAME_LENGTH); account.userid[23] = '\0';
memcpy(account.passwd,RFIFOP(fd, 26),NAME_LENGTH); account.passwd[23] = '\0';
account.passwdenc = 0;
server_name = (char*)RFIFOP(fd,60);
server_name[20] = '\0';
ShowInfo("server connection request %s @ %d.%d.%d.%d:%d (%d.%d.%d.%d)\n",
server_name, RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58),
p[0], p[1], p[2], p[3]);
jstrescapecpy(t_uid,server_name);
server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0';
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 (ip: %s)\n",
server_name, CONVIP(server_ip), server_port, ip);
jstrescapecpy(t_uid, server_name);
if (login_config.log_login)
{
char t_login[50];
jstrescapecpy(t_login,account.userid);
sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s@%s','100', 'charserver - %s@%d.%d.%d.%d:%d')",
loginlog_db, (unsigned int)ntohl(ipl),
t_login, t_uid, t_uid,
RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57),
RFIFOW(fd, 58));
loginlog_db, ipl, t_login, t_uid, t_uid, CONVIP(server_ip), server_port);
//query
if(mysql_query(&mysql_handle, tmpsql)) {
@ -1648,19 +1646,18 @@ int parse_login(int fd)
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
}
}
result = mmo_auth(&account, fd);
//printf("Result: %d - Sex: %d - Account ID: %d\n",result,account.sex,(int) account.account_id);
if(result == -1 && account.sex==2 && account.account_id<MAX_SERVERS && server_fd[account.account_id]==-1){
result = mmo_auth(&account, fd);
if (result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1) {
ShowStatus("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=RFIFOL(fd,54);
server[account.account_id].port=RFIFOW(fd,58);
memcpy(server[account.account_id].name,server_name,20);
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].ip = ntohl(RFIFOL(fd,54));
server[account.account_id].port = ntohs(RFIFOW(fd,58));
memcpy(server[account.account_id].name, server_name, 20);
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;
sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%d'", account.account_id);
//query
if(mysql_query(&mysql_handle, tmpsql)) {
@ -1675,42 +1672,43 @@ int parse_login(int fd)
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql);
}
WFIFOW(fd,0)=0x2711;
WFIFOB(fd,2)=0;
WFIFOW(fd,0) = 0x2711;
WFIFOB(fd,2) = 0;
WFIFOSET(fd,3);
session[fd]->func_parse=parse_fromchar;
realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK);
session[fd]->func_parse = parse_fromchar;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
// send GM account to char-server
send_GM_accounts(fd);
} else {
WFIFOW(fd, 0) =0x2711;
WFIFOB(fd, 2)=3;
WFIFOSET(fd, 3);
WFIFOW(fd,0) = 0x2711;
WFIFOB(fd,2) = 3;
WFIFOSET(fd,3);
}
}
RFIFOSKIP(fd, 86);
RFIFOSKIP(fd,86);
return 0;
case 0x7530: // request Athena information
{
ShowInfo ("Athena version check...\n");
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;
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);
ShowInfo ("Athena version check...\n");
break;
}
case 0x7532:
case 0x7532: // Request to end connection
ShowStatus ("End of connection (ip: %s)" RETCODE, ip);
session[fd]->eof = 1;
break;
default:
ShowStatus ("Abnormal end of connection (ip: %s): Unknown packet 0x%x " RETCODE, ip, RFIFOW(fd,0));
session[fd]->eof = 1;
@ -1782,7 +1780,6 @@ int config_switch(const char *str)
return atoi(str);
}
//----------------------------------
// Reading Lan Support configuration
//----------------------------------
@ -1819,9 +1816,9 @@ int login_lan_config_read(const char *lancfgName)
if(strcmpi(w1, "subnet") == 0) {
subnet[subnet_count].mask = inet_addr(w2);
subnet[subnet_count].char_ip = inet_addr(w3);
subnet[subnet_count].map_ip = inet_addr(w4);
subnet[subnet_count].mask = ntohl(inet_addr(w2));
subnet[subnet_count].char_ip = ntohl(inet_addr(w3));
subnet[subnet_count].map_ip = ntohl(inet_addr(w4));
subnet[subnet_count].subnet = subnet[subnet_count].char_ip&subnet[subnet_count].mask;
if (subnet[subnet_count].subnet != (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);
@ -1851,9 +1848,9 @@ int ip_ban_flush(int tid, unsigned int tick, int id, int data)
return 0;
}
//-----------------------------------------------------
//-----------------------------------
// Reading main configuration file
//-----------------------------------------------------
//-----------------------------------
int login_config_read(const char* cfgName)
{
char line[1024], w1[1024], w2[1024];
@ -1867,11 +1864,12 @@ int login_config_read(const char* cfgName)
{
if (line[0] == '/' && line[1] == '/')
continue;
if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
continue;
remove_control_chars((unsigned char *) w1);
remove_control_chars((unsigned char *) w2);
remove_control_chars((unsigned char *)w1);
remove_control_chars((unsigned char *)w2);
if(!strcmpi(w1,"timestamp_format")) {
strncpy(timestamp_format, w2, 20);
@ -1890,6 +1888,9 @@ int login_config_read(const char* cfgName)
login_config.login_port = (unsigned short)atoi(w2);
ShowStatus("set login_port : %s\n",w2);
}
else if (!strcmpi(w1, "log_login"))
login_config.log_login = config_switch(w2);
else if (!strcmpi(w1,"ipban"))
login_config.ipban = config_switch(w2);
else if (!strcmpi(w1,"dynamic_pass_failure_ban"))
@ -1923,8 +1924,6 @@ int login_config_read(const char* cfgName)
time_allowed = atoi(w2);
else if (!strcmpi(w1, "online_check"))
login_config.online_check = config_switch(w2);
else if (!strcmpi(w1, "log_login"))
login_config.log_login = config_switch(w2);
else if (!strcmpi(w1,"use_dnsbl"))
login_config.use_dnsbl = config_switch(w2);
else if (!strcmpi(w1,"dnsbl_servers"))

View File

@ -42,8 +42,8 @@ struct mmo_account {
struct mmo_char_server {
char name[20];
long ip;
short port;
uint32 ip;
uint16 port;
int users;
int maintenance;
int new_;

View File

@ -24,13 +24,9 @@
#include "status.h"
#include "mercenary.h"
//Updated table (only doc^^) [Sirius]
//Used Packets: U->2af8
//Free Packets: F->2af8
struct dbt *auth_db;
static const int packet_len_table[0x3d] = {
static const int packet_len_table[0x3d] = { // U - used, F - free
60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
6,-1,18, 7,-1,49,30,10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
6,30,-1,10,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, U->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
@ -89,8 +85,8 @@ int chrif_connected = 0;
int char_fd = 0; //Using 0 instead of -1 is safer against crashes. [Skotlex]
int srvinfo;
static char char_ip_str[128];
static in_addr_t char_ip= 0;
static int char_port = 6121;
static uint32 char_ip = 0;
static uint16 char_port = 6121;
static char userid[NAME_LENGTH], passwd[NAME_LENGTH];
static int chrif_state = 0;
static int char_init_done = 0;
@ -103,29 +99,20 @@ int other_mapserver_count=0; //Holds count of how many other map servers are onl
//This define should spare writing the check in every function. [Skotlex]
#define chrif_check(a) { if(!chrif_isconnect()) return a; }
// 設定ファイル読み込み関係
/*==========================================
*
*------------------------------------------
*/
// sets char-server's user id
void chrif_setuserid(char *id)
{
memcpy(userid, id, NAME_LENGTH);
}
/*==========================================
*
*------------------------------------------
*/
// sets char-server's password
void chrif_setpasswd(char *pwd)
{
memcpy(passwd, pwd, NAME_LENGTH);
}
/*==========================================
*
*------------------------------------------
*/
// security check, prints warning if using default password
void chrif_checkdefaultlogin(void)
{
if (strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) {
@ -139,11 +126,8 @@ void chrif_checkdefaultlogin(void)
}
}
/*==========================================
*
*------------------------------------------
*/
int chrif_setip(const char *ip)
// sets char-server's ip address
int chrif_setip(const char* ip)
{
char ip_str[16];
char_ip = host2ip(ip);
@ -156,30 +140,23 @@ int chrif_setip(const char *ip)
return 1;
}
/*==========================================
*
*------------------------------------------
*/
void chrif_setport(int port)
// sets char-server's port number
void chrif_setport(uint16 port)
{
char_port = port;
}
/*==========================================
*
*------------------------------------------
*/
// says whether the char-server is connected or not
int chrif_isconnect(void)
{
return (char_fd > 0 && session[char_fd] != NULL && chrif_state == 2);
}
/*==========================================
* Saves char.
* Flag = 1: Character is quitting.
* Saves character data.
* Flag = 1: Character is quitting
* Flag = 2: Character is changing map-servers
*------------------------------------------
*/
*------------------------------------------*/
int chrif_save(struct map_session_data *sd, int flag)
{
nullpo_retr(-1, sd);
@ -226,10 +203,7 @@ int chrif_save(struct map_session_data *sd, int flag)
return 0;
}
/*==========================================
*
*------------------------------------------
*/
// connects to char-server (plaintext)
int chrif_connect(int fd)
{
ShowStatus("Logging in to char server...\n", char_fd);
@ -238,17 +212,14 @@ int chrif_connect(int fd)
memcpy(WFIFOP(fd,2), userid, NAME_LENGTH);
memcpy(WFIFOP(fd,26), passwd, NAME_LENGTH);
WFIFOL(fd,50) = 0;
WFIFOL(fd,54) = clif_getip_long();
WFIFOW(fd,58) = clif_getport(); // [Valaris] thanks to fov
WFIFOL(fd,54) = htonl(clif_getip());
WFIFOW(fd,58) = htons(clif_getport());
WFIFOSET(fd,60);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
// sends maps to char-server
int chrif_sendmap(int fd)
{
int i;
@ -263,36 +234,31 @@ int chrif_sendmap(int fd)
return 0;
}
/*==========================================
*
*------------------------------------------
*/
// receive maps from some other map-server (relayed via char-server)
int chrif_recvmap(int fd)
{
int i, j, ip, port;
unsigned char *p = (unsigned char *)&ip;
int i, j;
uint32 ip;
uint16 port;
RFIFOHEAD(fd);
ip = RFIFOL(fd,4);
port = RFIFOW(fd,8);
ip = ntohl(RFIFOL(fd,4));
port = ntohs(RFIFOW(fd,8));
for(i = 10, j = 0; i < RFIFOW(fd,2); i += 4, j++) {
map_setipport(RFIFOW(fd,i), ip, port);
// if (battle_config.etc_log)
// printf("recv map %d %s\n", j, RFIFOP(fd,i));
}
if (battle_config.etc_log)
ShowStatus("recv map on %d.%d.%d.%d:%d (%d maps)\n", p[0], p[1], p[2], p[3], port, j);
ShowStatus("Received maps from %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j);
other_mapserver_count++;
return 0;
}
/*==========================================
* Delete maps of other servers, (if an other mapserver is going OFF)
*------------------------------------------
*/
int chrif_removemap(int fd){
int i, j, ip, port;
unsigned char *p = (unsigned char *)&ip;
// remove specified maps (used when some other map-server disconnects)
int chrif_removemap(int fd)
{
int i, j;
uint32 ip;
uint16 port;
RFIFOHEAD(fd);
ip = RFIFOL(fd, 4);
@ -304,11 +270,13 @@ int chrif_removemap(int fd){
other_mapserver_count--;
if(battle_config.etc_log)
ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", p[0], p[1], p[2], p[3], port, j);
ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j);
return 0;
}
int chrif_save_ack(int fd) {
// received after a character has been "final saved" on the char-server
int chrif_save_ack(int fd)
{
struct map_session_data *sd;
RFIFOHEAD(fd);
sd = map_id2sd(RFIFOL(fd,2));
@ -318,13 +286,10 @@ int chrif_save_ack(int fd) {
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y, int ip, short port)
// request to move a character between mapservers
int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y, uint32 ip, uint16 port)
{
int s_ip;
uint32 s_ip;
nullpo_retr(-1, sd);
@ -337,7 +302,7 @@ int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y,
}
if (sd->fd && sd->fd < fd_max && session[sd->fd])
s_ip = session[sd->fd]->client_addr.sin_addr.s_addr;
s_ip = session[sd->fd]->client_addr;
else //Not connected? Can't retrieve IP
s_ip = 0;
@ -350,19 +315,16 @@ int chrif_changemapserver(struct map_session_data *sd, short map, int x, int y,
WFIFOW(char_fd,18) = map;
WFIFOW(char_fd,20) = x;
WFIFOW(char_fd,22) = y;
WFIFOL(char_fd,24) = ip;
WFIFOW(char_fd,28) = port;
WFIFOL(char_fd,24) = htonl(ip);
WFIFOW(char_fd,28) = htons(port);
WFIFOB(char_fd,30) = sd->status.sex;
WFIFOL(char_fd,31) = s_ip;
WFIFOL(char_fd,31) = htonl(s_ip); // not used
WFIFOSET(char_fd,35);
return 0;
}
/*==========================================
* ack
*------------------------------------------
*/
// map-server change request acknowledgement (positive or negative)
int chrif_changemapserverack(int fd)
{
struct map_session_data *sd;
@ -380,7 +342,7 @@ int chrif_changemapserverack(int fd)
return 0;
}
sprintf(mapname, "%s.gat", mapindex_id2name(RFIFOW(fd,18)));
clif_changemapserver(sd, mapname, RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28));
clif_changemapserver(sd, mapname, RFIFOW(fd,20), RFIFOW(fd,22), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28)));
//Player has been saved already, remove him from memory. [Skotlex]
map_quit(sd);
@ -390,8 +352,7 @@ int chrif_changemapserverack(int fd)
/*==========================================
*
*------------------------------------------
*/
*------------------------------------------*/
int chrif_connectack(int fd)
{
RFIFOHEAD(fd);
@ -568,7 +529,7 @@ int auth_db_cleanup(int tid, unsigned int tick, int id, int data) {
*
*------------------------------------------
*/
int chrif_charselectreq(struct map_session_data *sd, unsigned long s_ip)
int chrif_charselectreq(struct map_session_data* sd, uint32 s_ip)
{
nullpo_retr(-1, sd);
@ -581,7 +542,7 @@ int chrif_charselectreq(struct map_session_data *sd, unsigned long s_ip)
WFIFOL(char_fd, 2) = sd->bl.id;
WFIFOL(char_fd, 6) = sd->login_id1;
WFIFOL(char_fd,10) = sd->login_id2;
WFIFOL(char_fd,14) = s_ip;
WFIFOL(char_fd,14) = htonl(s_ip);
WFIFOSET(char_fd,18);
return 0;
@ -693,7 +654,6 @@ int chrif_changesex(int id, int sex) {
WFIFOW(char_fd,2) = 9;
WFIFOL(char_fd,4) = id;
WFIFOB(char_fd,8) = sex;
// ShowInfo("chrif : sent 0x3000(changesex)\n");
WFIFOSET(char_fd,9);
return 0;
}
@ -1040,7 +1000,8 @@ int chrif_accountban(int fd)
//Disconnect the player out of the game, simple packet
//packet.w AID.L WHY.B 2+4+1 = 7byte
int chrif_disconnectplayer(int fd){
int chrif_disconnectplayer(int fd)
{
struct map_session_data *sd;
RFIFOHEAD(fd);
@ -1419,7 +1380,7 @@ int chrif_disconnect(int fd) {
void chrif_update_ip(int fd)
{
unsigned long new_ip;
uint32 new_ip;
WFIFOHEAD(fd, 6);
new_ip = host2ip(char_ip_str);
if (new_ip && new_ip != char_ip)
@ -1428,7 +1389,7 @@ void chrif_update_ip(int fd)
new_ip = clif_refresh_ip();
if (!new_ip) return; //No change
WFIFOW(fd, 0) = 0x2736;
WFIFOL(fd, 2) = new_ip;
WFIFOL(fd, 2) = htonl(new_ip);
WFIFOSET(fd, 6);
}
@ -1452,7 +1413,7 @@ int chrif_parse(int fd)
return 0;
}
while (RFIFOREST(fd) >= 2 && !session[fd]->eof) { //Infinite loop on broken pipe fix. [Skotlex]
while (RFIFOREST(fd) >= 2) { //Infinite loop on broken pipe fix. [Skotlex]
RFIFOHEAD(fd);
cmd = RFIFOW(fd,0);
if (cmd < 0x2af8 || cmd >= 0x2af8 + (sizeof(packet_len_table) / sizeof(packet_len_table[0])) ||

View File

@ -12,11 +12,11 @@ struct auth_node{
unsigned int node_created; //For node auto-deleting
};
void chrif_setuserid(char*);
void chrif_setpasswd(char*);
void chrif_setuserid(char* id);
void chrif_setpasswd(char* pwd);
void chrif_checkdefaultlogin(void);
int chrif_setip(const char*);
void chrif_setport(int);
int chrif_setip(const char* ip);
void chrif_setport(uint16 port);
int chrif_isconnect(void);
@ -27,9 +27,9 @@ void chrif_authreq(struct map_session_data *);
void chrif_authok(int fd);
int chrif_scdata_request(int account_id, int char_id);
int chrif_save(struct map_session_data*, int flag);
int chrif_charselectreq(struct map_session_data *sd, unsigned long s_ip);
int chrif_charselectreq(struct map_session_data*sd, uint32 s_ip);
void check_fake_id(int fd, struct map_session_data *sd, int target_id);
int chrif_changemapserver(struct map_session_data *sd,short map,int x,int y,int ip,short port);
int chrif_changemapserver(struct map_session_data*sd, short map, int x, int y, uint32 ip, uint16 port);
int chrif_searchcharid(int char_id);
int chrif_changegm(int id,const char *pass,int len);

View File

@ -96,9 +96,9 @@ struct packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB];
//Guarantees that the given string does not exceeds the allowed size, as well as making sure it's null terminated. [Skotlex\]
#define mes_len_check(mes, len, max) if (len > max) { mes[max-1] = '\0'; len = max; } else mes[len-1] = '\0';
static char map_ip_str[128];
static in_addr_t map_ip;
static in_addr_t bind_ip = INADDR_ANY;
static int map_port = 5121;
static uint32 map_ip;
static uint32 bind_ip = INADDR_ANY;
static uint16 map_port = 5121;
int map_fd;
//These two will be used to verify the incoming player's validity.
@ -142,7 +142,7 @@ void clif_setbindip(const char* ip)
* map鯖のport設定
*------------------------------------------
*/
void clif_setport(int port)
void clif_setport(uint16 port)
{
map_port = port;
}
@ -151,27 +151,21 @@ void clif_setport(int port)
* map鯖のip読み出し
*------------------------------------------
*/
in_addr_t clif_getip(void)
uint32 clif_getip(void)
{
return map_ip;
}
//Returns the ip casted as a basic type, to avoid needing to include the socket/net related libs by calling modules.
unsigned long clif_getip_long(void)
{
return (unsigned long)map_ip;
}
//Refreshes map_server ip, returns the new ip if the ip changed, otherwise it returns 0.
unsigned long clif_refresh_ip(void)
uint32 clif_refresh_ip(void)
{
in_addr_t new_ip;
uint32 new_ip;
new_ip = host2ip(map_ip_str);
if (new_ip && new_ip != map_ip) {
map_ip = new_ip;
ShowInfo("Updating IP resolution of [%s].\n",map_ip_str);
return (unsigned long)map_ip;
ShowInfo("Updating IP resolution of [%s].\n", map_ip_str);
return map_ip;
}
return 0;
}
@ -180,7 +174,7 @@ unsigned long clif_refresh_ip(void)
* map鯖のport読み出し
*------------------------------------------
*/
int clif_getport(void)
uint16 clif_getport(void)
{
return map_port;
}
@ -1625,10 +1619,10 @@ int clif_changemap(struct map_session_data *sd, short map, int x, int y) {
}
/*==========================================
*
*------------------------------------------
*/
int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x, int y, int ip, int port) {
* Tells the client to connect to another map-server
*------------------------------------------*/
int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x, int y, uint32 ip, uint16 port)
{
int fd;
nullpo_retr(0, sd);
@ -1641,8 +1635,8 @@ int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x
WFIFOB(fd,17) = 0; //Null terminator for mapname
WFIFOW(fd,18) = x;
WFIFOW(fd,20) = y;
WFIFOL(fd,22) = ip;
WFIFOW(fd,26) = port;
WFIFOL(fd,22) = htonl(ip);
WFIFOW(fd,26) = port; // /!\ must be sent in intel host byte order /!\ (client bug)
WFIFOSET(fd, packet_len(0x92));
return 0;
@ -8862,7 +8856,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
/* Rovert's Prevent logout option - Fixed [Valaris] */
if (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout)
{ //Send to char-server for character selection.
chrif_charselectreq(sd, session[fd]->client_addr.sin_addr.s_addr);
chrif_charselectreq(sd, session[fd]->client_addr);
} else {
WFIFOHEAD(fd,packet_len(0x18b));
WFIFOW(fd,0)=0x18b;
@ -11746,7 +11740,8 @@ void clif_parse_debug(int fd,struct map_session_data *sd)
* socket.cのdo_parsepacketから呼び出される
*------------------------------------------
*/
int clif_parse(int fd) {
int clif_parse(int fd)
{
int packet_len = 0, cmd, packet_ver, err, dump = 0;
TBL_PC *sd;
RFIFOHEAD(fd);
@ -11772,8 +11767,8 @@ int clif_parse(int fd) {
map_quit(sd);
}
} else {
unsigned char *ip = (unsigned char *) &session[fd]->client_addr.sin_addr;
ShowInfo("Closed connection from '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", ip[0],ip[1],ip[2],ip[3]);
uint32 ip = session[fd]->client_addr;
ShowInfo("Closed connection from '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\n", CONVIP(ip));
}
do_close(fd);
return 0;
@ -12321,8 +12316,8 @@ static int packetdb_readdb(void)
*
*------------------------------------------
*/
int do_init_clif(void) {
int do_init_clif(void)
{
clif_config.packet_db_ver = -1; // the main packet version of the DB
memset(clif_config.connect_cmd, 0, sizeof(clif_config.connect_cmd)); //The default connect command will be determined after reading the packet_db [Skotlex]

View File

@ -52,11 +52,11 @@ extern struct packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB];
int clif_setip(const char* ip);
void clif_setbindip(const char* ip);
void clif_setport(int);
void clif_setport(uint16 port);
unsigned long clif_getip_long(void);
unsigned long clif_refresh_ip(void);
int clif_getport(void);
uint32 clif_getip(void);
uint32 clif_refresh_ip(void);
uint16 clif_getport(void);
int clif_countusers(void);
void clif_setwaitclose(int);
@ -75,7 +75,7 @@ int clif_spawn(struct block_list*); //area
int clif_walkok(struct map_session_data*); // self
void clif_move(struct unit_data *ud); //area
int clif_changemap(struct map_session_data*,short,int,int); //self
int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x, int y, int ip, int port); //self
int clif_changemapserver(struct map_session_data* sd, const char* mapname, int x, int y, uint32 ip, uint16 port); //self
int clif_blown(struct block_list *); // area
int clif_slide(struct block_list *,int,int); // area
int clif_fixpos(struct block_list *); // area

View File

@ -2077,9 +2077,9 @@ int map_mapindex2mapid(unsigned short mapindex) {
/*==========================================
* map名からip,port?
*------------------------------------------
*/
int map_mapname2ipport(unsigned short name,int *ip,int *port) {
*------------------------------------------*/
int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port)
{
struct map_data_other_server *mdos=NULL;
mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)name);
@ -2349,16 +2349,17 @@ static void* create_map_data_other_server(DBKey key, va_list args) {
}
/*==========================================
* dbに追加
*------------------------------------------
*/
int map_setipport(unsigned short mapindex,unsigned long ip,int port) {
*------------------------------------------*/
int map_setipport(unsigned short mapindex, uint32 ip, uint16 port)
{
struct map_data_other_server *mdos=NULL;
mdos=(struct map_data_other_server *)uidb_ensure(map_db,(unsigned int)mapindex, create_map_data_other_server);
if(mdos->gat) //Local map,Do nothing. Give priority to our own local maps over ones from another server. [Skotlex]
return 0;
if(ip == clif_getip_long() && port == clif_getport()) {
if(ip == clif_getip() && port == clif_getport()) {
//That's odd, we received info that we are the ones with this map, but... we don't have it.
ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(mapindex));
exit(1);
@ -2388,12 +2389,10 @@ int map_eraseallipport(void) {
/*==========================================
* dbから削除
*------------------------------------------
*/
int map_eraseipport(unsigned short mapindex,unsigned long ip,int port)
*------------------------------------------*/
int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port)
{
struct map_data_other_server *mdos;
// unsigned char *p=(unsigned char *)&ip;
mdos = uidb_get(map_db,(unsigned int)mapindex);
if(!mdos || mdos->gat) //Map either does not exists or is a local map.

View File

@ -1109,8 +1109,8 @@ struct map_data_other_server {
char name[MAP_NAME_LENGTH];
unsigned short index; //Index is the map index used by the mapindex* functions.
unsigned char *gat; // NULL固定にして判断
unsigned long ip;
unsigned int port;
uint32 ip;
uint16 port;
};
struct flooritem_data {
@ -1339,9 +1339,9 @@ struct map_session_data * map_id2sd(int);
struct block_list * map_id2bl(int);
int map_mapindex2mapid(unsigned short mapindex);
int map_mapname2mapid(const char* name);
int map_mapname2ipport(unsigned short,int*,int*);
int map_setipport(unsigned short map,unsigned long ip,int port);
int map_eraseipport(unsigned short map,unsigned long ip,int port);
int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port);
int map_setipport(unsigned short map, uint32 ip, uint16 port);
int map_eraseipport(unsigned short map, uint32 ip, uint16 port);
int map_eraseallipport(void);
void map_addiddb(struct block_list *);
void map_deliddb(struct block_list *bl);

View File

@ -698,20 +698,20 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
sd->state.event_kill_mob = 1;
{ //Add IP field
unsigned char *ip = (unsigned char *) &session[sd->fd]->client_addr.sin_addr;
uint32 ip = session[sd->fd]->client_addr;
if (pc_isGM(sd))
ShowInfo("GM '"CL_WHITE"%s"CL_RESET"' logged in."
" (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"',"
" Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"',"
" GM Level '"CL_WHITE"%d"CL_RESET"').\n",
sd->status.name, sd->status.account_id, sd->status.char_id,
sd->packet_ver, ip[0],ip[1],ip[2],ip[3], pc_isGM(sd));
sd->packet_ver, CONVIP(ip), pc_isGM(sd));
else
ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in."
" (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"',"
" Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"').\n",
sd->status.name, sd->status.account_id, sd->status.char_id,
sd->packet_ver, ip[0],ip[1],ip[2],ip[3]);
sd->packet_ver, CONVIP(ip));
}
// Send friends list
@ -3371,10 +3371,11 @@ int pc_setpos(struct map_session_data *sd,unsigned short mapindex,int x,int y,in
sd->regen.state.gc = 0;
}
if(m<0){
if(sd->mapindex){
int ip,port;
if(map_mapname2ipport(mapindex,&ip,&port)==0){
if(m<0) {
if(sd->mapindex) {
uint32 ip;
uint16 port;
if(map_mapname2ipport(mapindex,&ip,&port)==0) {
unit_remove_map(&sd->bl,clrtype);
sd->mapindex = mapindex;
sd->bl.x=x;