summaryrefslogtreecommitdiff
path: root/src/char/char.c
diff options
context:
space:
mode:
authorultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-04-05 18:49:57 +0000
committerultramage <ultramage@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-04-05 18:49:57 +0000
commit88a5d0cdda513357496b9d53878618e1620f47e8 (patch)
tree4f3c2bedbac4b715ff783de5e1c8d1aefe4395af /src/char/char.c
parenta7fd6bfe9bcce1862b554f5841d9ff1aedf473e3 (diff)
downloadhercules-88a5d0cdda513357496b9d53878618e1620f47e8.tar.gz
hercules-88a5d0cdda513357496b9d53878618e1620f47e8.tar.bz2
hercules-88a5d0cdda513357496b9d53878618e1620f47e8.tar.xz
hercules-88a5d0cdda513357496b9d53878618e1620f47e8.zip
* 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://rathena.svn.sourceforge.net/svnroot/rathena/trunk@10162 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/char/char.c')
-rw-r--r--src/char/char.c426
1 files changed, 205 insertions, 221 deletions
diff --git a/src/char/char.c b/src/char/char.c
index a09ca72dd..65e1dc3e6 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -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,71 +2752,70 @@ 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);
- 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);
-
- 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]
- }
+
+ ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n",
+ 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, 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);
+ unsigned char buf[16384];
+ int x;
+ if (j == 0) {
+ 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
- } else {
- WBUFW(buf,0) = 0x2b04;
- WBUFW(buf,2) = j * 4 + 10;
- WBUFL(buf,4) = server[id].ip;
- WBUFW(buf,8) = server[id].port;
- memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4);
- mapif_sendallwos(fd, buf, WBUFW(buf,2));
- }
- // Transmitting the maps of the other map-servers to the new map-server
- for(x = 0; x < MAX_MAP_SERVERS; x++) {
- if (server_fd[x] >= 0 && x != id) {
- WFIFOW(fd,0) = 0x2b04;
- WFIFOL(fd,4) = server[x].ip;
- WFIFOW(fd,8) = server[x].port;
- j = 0;
- for(i = 0; i < MAX_MAP_PER_SERVER; i++)
- if (server[x].map[i])
- WFIFOW(fd,10+(j++)*4) = server[x].map[i];
- if (j > 0) {
- WFIFOW(fd,2) = j * 4 + 10;
- WFIFOSET(fd,WFIFOW(fd,2));
- }
+ WBUFW(buf,0) = 0x2b04;
+ WBUFW(buf,2) = j * 4 + 10;
+ 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));
+ }
+ // Transmitting the maps of the other map-servers to the new map-server
+ for(x = 0; x < MAX_MAP_SERVERS; x++) {
+ if (server_fd[x] >= 0 && x != id) {
+ WFIFOW(fd,0) = 0x2b04;
+ 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])
+ WFIFOW(fd,10+(j++)*4) = server[x].map[i];
+ if (j > 0) {
+ WFIFOW(fd,2) = j * 4 + 10;
+ WFIFOSET(fd,WFIFOW(fd,2));
}
}
}
+ }
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管理パケット
@@ -3412,9 +3395,10 @@ int parse_char(int fd) {
case 0x65: // 接続要求
if (RFIFOREST(fd) < 17)
return 0;
- {
+ {
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,20 +3441,20 @@ 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);
}
}
- }
+ }
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;
}
- 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]
-
+ 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);
}
}