extern int handle_anongame_packet(t_connection * c, t_packet const * const packet) { switch (bn_byte_get(packet->u.client_anongame.option)) { case CLIENT_FINDANONGAME_PROFILE: return _client_anongame_profile(c, packet); case CLIENT_FINDANONGAME_CANCEL: return _client_anongame_cancel(c); case CLIENT_FINDANONGAME_SEARCH: case CLIENT_FINDANONGAME_AT_INVITER_SEARCH: case CLIENT_FINDANONGAME_AT_SEARCH: return handle_anongame_search(c, packet); /* located in anongame.c */ case CLIENT_FINDANONGAME_GET_ICON: return _client_anongame_get_icon(c, packet); case CLIENT_FINDANONGAME_SET_ICON: return _client_anongame_set_icon(c, packet); case CLIENT_FINDANONGAME_INFOS: return _client_anongame_infos(c, packet); case CLIENT_ANONGAME_TOURNAMENT: return _client_anongame_tournament(c, packet); case CLIENT_FINDANONGAME_PROFILE_CLAN: return _client_anongame_profile_clan(c, packet); default: eventlog(eventlog_level_error, __FUNCTION__, "got unhandled option %d", bn_byte_get(packet->u.client_findanongame.option)); return -1; } }
static int on_d2cs_gameinforeply(t_connection * c, t_packet const * packet) { t_game * game; char const * gamename; unsigned int difficulty; t_game_difficulty diff; if (!(c)) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection"); return -1; } if (!(gamename = packet_get_str_const(packet,sizeof(t_d2cs_bnetd_gameinforeply),GAME_NAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"missing or too long gamename"); return -1; } if (!(game = gamelist_find_game(gamename,CLIENTTAG_DIABLO2DV_UINT,game_type_diablo2closed)) && !(game = gamelist_find_game(gamename,CLIENTTAG_DIABLO2XP_UINT,game_type_diablo2closed))) { eventlog(eventlog_level_error,__FUNCTION__,"reply for unknown game \"%s\"",gamename); return -1; } difficulty = bn_byte_get(packet->u.d2cs_bnetd_gameinforeply.difficulty); switch (difficulty) { case 0: diff = game_difficulty_normal; break; case 1: diff = game_difficulty_nightmare; break; case 2: diff = game_difficulty_hell; break; default: diff = game_difficulty_none; } game_set_difficulty(game,diff); return 0; }
extern int d2cs_handle_init_packet(t_connection * c, t_packet * packet) { int classs; int retval; ASSERT(c,-1); ASSERT(packet,-1); classs=bn_byte_get(packet->u.client_initconn.classs); switch (classs) { case CLIENT_INITCONN_CLASS_D2CS: retval=on_d2cs_initconn(c); break; case CLIENT_INITCONN_CLASS_D2GS: retval=on_d2gs_initconn(c); break; default: eventlog(eventlog_level_error,__FUNCTION__,"got bad connection classs %d",classs); retval=-1; break; } return retval; }
static int _client_anongame_infos(t_connection * c, t_packet const * const packet) { t_packet * rpacket; if (bn_int_get(packet->u.client_findanongame_inforeq.count) > 1) { /* reply with 0 entries found */ int temp = 0; if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } packet_set_size(rpacket, sizeof(t_server_findanongame_inforeply)); packet_set_type(rpacket, SERVER_FINDANONGAME_INFOREPLY); bn_byte_set(&rpacket->u.server_findanongame_inforeply.option, CLIENT_FINDANONGAME_INFOS); bn_int_set(&rpacket->u.server_findanongame_inforeply.count, bn_int_get(packet->u.client_findanongame_inforeq.count)); bn_byte_set(&rpacket->u.server_findanongame_inforeply.noitems, 0); packet_append_data(rpacket, &temp, 1); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } else { int i; int client_tag; int server_tag_count = 0; int client_tag_unk; int server_tag_unk; bn_int temp; char noitems; char * tmpdata; int tmplen; t_clienttag clienttag = conn_get_clienttag(c); char last_packet = 0x00; char other_packet = 0x01; char langstr[5]; t_gamelang gamelang = conn_get_gamelang(c); bn_int_tag_get((bn_int const *)&gamelang, langstr, 5); /* Send seperate packet for each item requested * sending all at once overloaded w3xp * [Omega] */ for (i = 0; i < bn_byte_get(packet->u.client_findanongame_inforeq.noitems); i++){ noitems = 0; if ((rpacket = packet_create(packet_class_bnet)) == NULL) { eventlog(eventlog_level_error, __FUNCTION__, "could not create new packet"); return -1; } /* Starting the packet stuff */ packet_set_size(rpacket, sizeof(t_server_findanongame_inforeply)); packet_set_type(rpacket, SERVER_FINDANONGAME_INFOREPLY); bn_byte_set(&rpacket->u.server_findanongame_inforeply.option, CLIENT_FINDANONGAME_INFOS); bn_int_set(&rpacket->u.server_findanongame_inforeply.count, 1); std::memcpy(&temp, (packet_get_data_const(packet, 10 + (i * 8), 4)), sizeof(int)); client_tag = bn_int_get(temp); std::memcpy(&temp, packet_get_data_const(packet, 14 + (i * 8), 4), sizeof(int)); client_tag_unk = bn_int_get(temp); switch (client_tag){ case CLIENT_FINDANONGAME_INFOTAG_URL: bn_int_set((bn_int*)&server_tag_unk, 0xBF1F1047); packet_append_data(rpacket, "LRU\0", 4); packet_append_data(rpacket, &server_tag_unk, 4); // FIXME: Maybe need do do some checks to avoid prefs empty strings. tmpdata = anongame_infos_data_get_url(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_URL", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_MAP: bn_int_set((bn_int*)&server_tag_unk, 0x70E2E0D5); packet_append_data(rpacket, "PAM\0", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_map(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_MAP", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_TYPE: bn_int_set((bn_int*)&server_tag_unk, 0x7C87DEEE); packet_append_data(rpacket, "EPYT", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_type(clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_TYPE", client_tag_unk); break; case CLIENT_FINDANONGAME_INFOTAG_DESC: bn_int_set((bn_int*)&server_tag_unk, 0xA4F0A22F); packet_append_data(rpacket, "CSED", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_desc(langstr, clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_DESC", client_tag_unk); noitems++; server_tag_count++; break; case CLIENT_FINDANONGAME_INFOTAG_LADR: bn_int_set((bn_int*)&server_tag_unk, 0x3BADE25A); packet_append_data(rpacket, "RDAL", 4); packet_append_data(rpacket, &server_tag_unk, 4); tmpdata = anongame_infos_data_get_ladr(langstr, clienttag, conn_get_versionid(c), &tmplen); packet_append_data(rpacket, tmpdata, tmplen); noitems++; server_tag_count++; eventlog(eventlog_level_debug, __FUNCTION__, "client_tag request tagid=(0x%01x) tag=(%s) tag_unk=(0x%04x)", i, "CLIENT_FINDANONGAME_INFOTAG_LADR", client_tag_unk); break; default: eventlog(eventlog_level_debug, __FUNCTION__, "unrec client_tag request tagid=(0x%01x) tag=(0x%04x)", i, client_tag); } //Adding a last padding null-byte if (server_tag_count == bn_byte_get(packet->u.client_findanongame_inforeq.noitems)) packet_append_data(rpacket, &last_packet, 1); /* only last packet in group gets 0x00 */ else packet_append_data(rpacket, &other_packet, 1); /* the rest get 0x01 */ //Go,go,go bn_byte_set(&rpacket->u.server_findanongame_inforeply.noitems, noitems); conn_push_outqueue(c, rpacket); packet_del_ref(rpacket); } } return 0; }
extern int handle_init_packet(t_connection * c, t_packet const * const packet) { if (!c) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c)); return -1; } if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c)); return -1; } if (packet_get_class(packet)!=packet_class_init) { eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet)); return -1; } switch (packet_get_type(packet)) { case CLIENT_INITCONN: switch (bn_byte_get(packet->u.client_initconn.classs)) { case CLIENT_INITCONN_CLASS_BNET: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated bnet connection",conn_get_socket(c)); conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_bnet); break; case CLIENT_INITCONN_CLASS_FILE: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated file download connection",conn_get_socket(c)); conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_file); break; case CLIENT_INITCONN_CLASS_BOT: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated chat bot connection",conn_get_socket(c)); conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_bot); break; case CLIENT_INITCONN_CLASS_TELNET: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated telnet connection",conn_get_socket(c)); conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_telnet); break; case CLIENT_INITCONN_CLASS_D2CS_BNETD: { eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated d2cs_bnetd connection",conn_get_socket(c)); if (!(realmlist_find_realm_by_ip(conn_get_addr(c)))) { eventlog(eventlog_level_info,__FUNCTION__, "[%d] d2cs connection from unknown ip address %s",conn_get_socket(c),addr_num_to_addr_str(conn_get_addr(c),conn_get_port(c))); return -1; } conn_set_state(c,conn_state_connected); conn_set_class(c,conn_class_d2cs_bnetd); if (handle_d2cs_init(c)<0) { eventlog(eventlog_level_info,__FUNCTION__,"faild to init d2cs connection"); return -1; } } break; case CLIENT_INITCONN_CLASS_ENC: eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated encrypted connection (not supported)",conn_get_socket(c)); return -1; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] client requested unknown classs 0x%02x (length %d) (closing connection)",conn_get_socket(c),(unsigned int)bn_byte_get(packet->u.client_initconn.classs),packet_get_size(packet)); return -1; } break; default: eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown init packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet)); return -1; } return 0; }
extern char const * packet_get_type_str(t_packet const * packet, t_packet_dir dir) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return "unknown"; } switch (dir) { case packet_dir_from_client: switch (packet->pclass) { case packet_class_init: return "CLIENT_INITCONN"; case packet_class_bnet: if (packet_get_size(packet)<sizeof(t_bnet_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.bnet.h.type)) { case CLIENT_COMPINFO1: return "CLIENT_COMPINFO1"; case CLIENT_COMPINFO2: return "CLIENT_COMPINFO2"; case CLIENT_COUNTRYINFO1: return "CLIENT_COUNTRYINFO1"; case CLIENT_COUNTRYINFO_109: return "CLIENT_COUNTRYINFO_109"; case CLIENT_CREATEACCTREQ1: return "CLIENT_CREATEACCTREQ1"; case CLIENT_UNKNOWN_2B: return "CLIENT_UNKNOWN_2B"; case CLIENT_PROGIDENT: return "CLIENT_PROGIDENT"; case CLIENT_AUTHREQ1: return "CLIENT_AUTHREQ1"; case CLIENT_AUTHREQ_109: return "CLIENT_AUTHREQ_109"; case CLIENT_REGSNOOPREPLY: return "CLIENT_REGSNOOPREPLY"; case CLIENT_ICONREQ: return "CLIENT_ICONREQ"; case CLIENT_LADDERSEARCHREQ: return "CLIENT_LADDERSEARCHREQ"; case CLIENT_CDKEY: return "CLIENT_CDKEY"; case CLIENT_CDKEY2: return "CLIENT_CDKEY2"; case CLIENT_CDKEY3: return "CLIENT_CDKEY3"; case CLIENT_REALMLISTREQ: return "CLIENT_REALMLISTREQ"; case CLIENT_REALMLISTREQ_110: return "CLIENT_REALMLISTREQ_110"; case CLIENT_PROFILEREQ: return "CLIENT_PROFILEREQ"; case CLIENT_UNKNOWN_37: return "CLIENT_UNKNOWN_37"; case CLIENT_UNKNOWN_39: return "CLIENT_UNKNOWN_39"; case CLIENT_LOGINREQ2: return "CLIENT_LOGINREQ2"; case CLIENT_MOTD_W3: return "CLIENT_MOTD_W3"; case CLIENT_LOGINREQ_W3: return "CLIENT_LOGINREQ_W3"; case CLIENT_LOGONPROOFREQ: return "CLIENT_LOGONPROOFREQ"; case CLIENT_CREATEACCOUNT_W3: return "CLIENT_CREATEACCOUNT_W3"; case CLIENT_PASSCHANGEREQ: return "CLIENT_PASSCHANGEREQ"; case CLIENT_PASSCHANGEPROOFREQ: return "CLIENT_PASSCHANGEPROOFREQ"; case CLIENT_CHANGEGAMEPORT: return "CLIENT_CHANGEGAMEPORT"; case CLIENT_CREATEACCTREQ2: return "CLIENT_CREATEACCTREQ2"; case CLIENT_UDPOK: return "CLIENT_UDPOK"; case CLIENT_FILEINFOREQ: return "CLIENT_FILEINFOREQ"; case CLIENT_STATSREQ: return "CLIENT_STATSREQ"; case CLIENT_LOGINREQ1: return "CLIENT_LOGINREQ1"; case CLIENT_CHANGEPASSREQ: return "CLIENT_CHANGEPASSREQ"; case CLIENT_PLAYERINFOREQ: return "CLIENT_PLAYERINFOREQ"; case CLIENT_PROGIDENT2: return "CLIENT_PROGIDENT2"; case CLIENT_JOINCHANNEL: return "CLIENT_JOINCHANNEL"; case CLIENT_MESSAGE: return "CLIENT_MESSAGE"; case CLIENT_GAMELISTREQ: return "CLIENT_GAMELISTREQ"; case CLIENT_STARTGAME1: return "CLIENT_STARTGAME1"; case CLIENT_UNKNOWN_1B: return "CLIENT_UNKNOWN_1B"; case CLIENT_STARTGAME3: return "CLIENT_STARTGAME3"; case CLIENT_STARTGAME4: return "CLIENT_STARTGAME4"; case CLIENT_CLOSEGAME: return "CLIENT_CLOSEGAME"; case CLIENT_CLOSEGAME2: return "CLIENT_CLOSEGAME2"; case CLIENT_LEAVECHANNEL: return "CLIENT_LEAVECHANNEL"; case CLIENT_MAPAUTHREQ1: return "CLIENT_MAPAUTHREQ1"; case CLIENT_MAPAUTHREQ2: return "CLIENT_MAPAUTHREQ2"; case CLIENT_ADREQ: return "CLIENT_ADREQ"; case CLIENT_ADACK: return "CLIENT_ADACK"; case CLIENT_ADCLICK: return "CLIENT_ADCLICK"; case CLIENT_ADCLICK2: return "CLIENT_ADCLICK2"; case CLIENT_UNKNOWN_17: return "CLIENT_UNKNOWN_17"; case CLIENT_UNKNOWN_24: return "CLIENT_UNKNOWN_24"; case CLIENT_LADDERREQ: return "CLIENT_LADDERREQ"; case CLIENT_ECHOREPLY: return "CLIENT_ECHOREPLY"; case CLIENT_PINGREQ: return "CLIENT_PINGREQ"; case CLIENT_GAME_REPORT: return "CLIENT_GAME_REPORT"; case CLIENT_JOIN_GAME: return "CLIENT_JOIN_GAME"; case CLIENT_STATSUPDATE: return "CLIENT_STATSUPDATE"; case CLIENT_REALMJOINREQ_109: return "CLIENT_REALMJOINREQ_109"; case CLIENT_CHANGECLIENT: return "CLIENT_CHANGECLIENT"; case CLIENT_SETEMAILREPLY: return "CLIENT_SETEMAILREPLY"; case CLIENT_GETPASSWORDREQ: return "CLIENT_GETPASSWORDREQ"; case CLIENT_CHANGEEMAILREQ: return "CLIENT_CHANGEEMAILREQ"; case CLIENT_CRASHDUMP: return "CLIENT_CRASHDUMP"; case CLIENT_FINDANONGAME: return "CLIENT_FINDANONGAME"; case CLIENT_ARRANGEDTEAM_FRIENDSCREEN: return "CLIENT_ARRANGEDTEAM_FRIENDSCREEN"; case CLIENT_ARRANGEDTEAM_INVITE_FRIEND: return "CLIENT_ARRANGEDTEAM_INVITE_FRIEND"; case CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE: return "CLIENT_ARRANGEDTEAM_ACCEPT_DECLINE_INVITE"; case CLIENT_FRIENDSLISTREQ: return "CLIENT_FRIENDSLISTREQ"; case CLIENT_FRIENDINFOREQ: return "CLIENT_FRIENDINFOREQ"; case CLIENT_CLANINFOREQ: return "CLIENT_CLANINFOREQ"; case CLIENT_CLAN_CREATEREQ: return "CLIENT_CLAN_CREATEREQ"; case CLIENT_CLAN_CREATEINVITEREQ: return "CLIENT_CLAN_CREATEINVITEREQ"; case CLIENT_CLAN_CREATEINVITEREPLY: return "CLIENT_CLAN_CREATEINVITEREPLY"; case CLIENT_CLAN_DISBANDREQ: return "CLIENT_CLAN_DISBANDREQ"; case CLIENT_CLAN_MEMBERNEWCHIEFREQ: return "CLIENT_CLAN_MEMBERNEWCHIEFREQ"; case CLIENT_CLAN_INVITEREQ: return "CLIENT_CLAN_INVITEREQ"; case CLIENT_CLANMEMBER_REMOVE_REQ: return "CLIENT_CLANMEMBER_REMOVE_REQ"; case CLIENT_CLAN_INVITEREPLY: return "CLIENT_CLAN_INVITEREPLY"; case CLIENT_CLANMEMBER_RANKUPDATE_REQ: return "CLIENT_CLANMEMBER_RANKUPDATE_REQ"; case CLIENT_CLAN_MOTDCHG: return "CLIENT_CLAN_MOTDCHG"; case CLIENT_CLAN_MOTDREQ: return "CLIENT_CLAN_MOTDREQ"; case CLIENT_CLANMEMBERLIST_REQ: return "CLIENT_CLANMEMBERLIST_REQ"; } return "unknown"; case packet_class_file: if (packet_get_size(packet)<sizeof(t_file_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.file.h.type)) { case CLIENT_FILE_REQ: return "CLIENT_FILE_REQ"; } return "unknown"; case packet_class_udp: if (packet_get_size(packet)<sizeof(t_udp_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_int_get(packet->u.udp.h.type)) { case SERVER_UDPTEST: /* we get these if we send stuff to ourself */ return "SERVER_UDPTEST"; case CLIENT_UDPPING: return "CLIENT_UDPPING"; case CLIENT_SESSIONADDR1: return "CLIENT_SESSIONADDR1"; case CLIENT_SESSIONADDR2: return "CLIENT_SESSIONADDR2"; } return "unknown"; case packet_class_raw: return "CLIENT_RAW"; case packet_class_d2game: if (packet_get_size(packet)<sizeof(t_d2game_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_byte_get(packet->u.d2game.h.type)) { default: return "CLIENT_D2GAME"; } return "unknown"; case packet_class_d2cs: return "D2CS"; case packet_class_d2gs: return "D2GS"; case packet_class_d2cs_bnetd: return "D2CS_BNETD"; case packet_class_w3route: if (packet_get_size(packet)<sizeof(t_w3route_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.bnet.h.type)) { case CLIENT_W3ROUTE_REQ: return "CLIENT_W3ROUTE_REQ"; case CLIENT_W3ROUTE_LOADINGDONE: return "CLIENT_W3ROUTE_LOADINGDONE"; case CLIENT_W3ROUTE_ABORT: return "CLIENT_W3ROUTE_ABORT"; case CLIENT_W3ROUTE_CONNECTED: return "CLIENT_W3ROUTE_CONNECTED"; case CLIENT_W3ROUTE_ECHOREPLY: return "CLIENT_W3ROUTE_ECHOREPLY"; case CLIENT_W3ROUTE_GAMERESULT: return "CLIENT_W3ROUTE_GAMERESULT"; case CLIENT_W3ROUTE_GAMERESULT_W3XP: return "CLIENT_W3ROUTE_GAMERESULT_W3XP"; } return "unknown"; case packet_class_none: return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return "unknown"; case packet_dir_from_server: switch (packet->pclass) { case packet_class_init: return "unknown"; case packet_class_bnet: if (packet_get_size(packet)<sizeof(t_bnet_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.bnet.h.type)) { case SERVER_COMPREPLY: return "SERVER_COMPREPLY"; case SERVER_SESSIONKEY1: return "SERVER_SESSIONKEY1"; case SERVER_SESSIONKEY2: return "SERVER_SESSIONKEY2"; case SERVER_CREATEACCTREPLY1: return "SERVER_CREATEACCTREPLY1"; case SERVER_AUTHREQ1: return "SERVER_AUTHREQ1"; case SERVER_AUTHREQ_109: return "SERVER_AUTHREQ_109"; case SERVER_AUTHREPLY1: return "SERVER_AUTHREPLY1"; case SERVER_AUTHREPLY_109: return "SERVER_AUTHREPLY_109"; case SERVER_REGSNOOPREQ: return "SERVER_REGSNOOPREQ"; case SERVER_ICONREPLY: return "SERVER_ICONREPLY"; case SERVER_LADDERSEARCHREPLY: return "SERVER_LADDERSEARCHREPLY"; case SERVER_CDKEYREPLY: return "SERVER_CDKEYREPLY"; case SERVER_CDKEYREPLY2: return "SERVER_CDKEYREPLY2"; case SERVER_CDKEYREPLY3: return "SERVER_CDKEYREPLY3"; case SERVER_REALMLISTREPLY: return "SERVER_REALMLISTREPLY"; case SERVER_REALMLISTREPLY_110: return "SERVER_REALMLISTREPLY_110"; case SERVER_PROFILEREPLY: return "SERVER_PROFILEREPLY"; case SERVER_UNKNOWN_37: return "SERVER_UNKNOWN_37"; case SERVER_MOTD_W3: return "SERVER_MOTD_W3"; case SERVER_LOGINREPLY_W3: return "SERVER_LOGINREPLY_W3"; case SERVER_LOGONPROOFREPLY: return "SERVER_LOGONPROOFREPLY"; case SERVER_CREATEACCOUNT_W3: return "SERVER_CREATEACCOUNT_W3"; case SERVER_PASSCHANGEREPLY: return "SERVER_PASSCHANGEREPLY"; case SERVER_PASSCHANGEPROOFREPLY: return "SERVER_PASSCHANGEPROOFREPLY"; case SERVER_LOGINREPLY2: return "SERVER_LOGINREPLY2"; case SERVER_CREATEACCTREPLY2: return "SERVER_CREATEACCTREPLY2"; case SERVER_FILEINFOREPLY: return "SERVER_FILEINFOREPLY"; case SERVER_STATSREPLY: return "SERVER_STATSREPLY"; case SERVER_LOGINREPLY1: return "SERVER_LOGINREPLY1"; case SERVER_CHANGEPASSACK: return "SERVER_CHANGEPASSACK"; case SERVER_PLAYERINFOREPLY: return "SERVER_PLAYERINFOREPLY"; case SERVER_CHANNELLIST: return "SERVER_CHANNELLIST"; case SERVER_SERVERLIST: return "SERVER_SERVERLIST"; case SERVER_MESSAGE: return "SERVER_MESSAGE"; case SERVER_GAMELISTREPLY: return "SERVER_GAMELISTREPLY"; case SERVER_STARTGAME1_ACK: return "SERVER_STARTGAME1_ACK"; case SERVER_STARTGAME3_ACK: return "SERVER_STARTGAME3_ACK"; case SERVER_STARTGAME4_ACK: return "SERVER_STARTGAME4_ACK"; case SERVER_MAPAUTHREPLY1: return "SERVER_MAPAUTHREPLY1"; case SERVER_MAPAUTHREPLY2: return "SERVER_MAPAUTHREPLY2"; case SERVER_ADREPLY: return "SERVER_ADREPLY"; case SERVER_ADCLICKREPLY2: return "SERVER_ADCLICKREPLY2"; case SERVER_LADDERREPLY: return "SERVER_LADDERREPLY"; case SERVER_ECHOREQ: return "SERVER_ECHOREQ"; case SERVER_PINGREPLY: return "SERVER_PINGREPLY"; case SERVER_REALMJOINREPLY_109: return "SERVER_REALMJOINREPLY_109"; case SERVER_SETEMAILREQ: return "SERVER_SETEMAILREQ"; case SERVER_FINDANONGAME: return "SERVER_FINDANONGAME"; case SERVER_ARRANGEDTEAM_FRIENDSCREEN: return "SERVER_ARRANGEDTEAM_FRIENDSCREEN"; case SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK: return "SERVER_ARRANGEDTEAM_INVITE_FRIEND_ACK"; case SERVER_ARRANGEDTEAM_SEND_INVITE: return "SERVER_ARRANGEDTEAM_SEND_INVITE"; case SERVER_ARRANGEDTEAM_MEMBER_DECLINE: return "SERVER_ARRANGEDTEAM_MEMBER_DECLINE"; case SERVER_FRIENDSLISTREPLY: return "SERVER_FRIENDSLISTREPLY"; case SERVER_FRIENDINFOREPLY: return "SERVER_FRIENDINFOREPLY"; case SERVER_FRIENDADD_ACK: return "SERVER_FRIENDADD_ACK"; case SERVER_FRIENDDEL_ACK: return "SERVER_FRIENDDEL_ACK"; case SERVER_FRIENDMOVE_ACK: return "SERVER_FRIENDMOVE_ACK"; case SERVER_CLANINFOREPLY: return "SERVER_CLANINFO_REPLY"; case SERVER_CLAN_CREATEREPLY: return "SERVER_CLAN_CREATEREPLY"; case SERVER_CLAN_CREATEINVITEREPLY: return "SERVER_CLAN_CREATEINVITEREPLY"; case SERVER_CLAN_CREATEINVITEREQ: return "SERVER_CLAN_CREATEINVITEREQ"; case SERVER_CLAN_DISBANDREPLY: return "SERVER_CLAN_DISBANDREPLY"; case SERVER_CLAN_MEMBERNEWCHIEFREPLY: return "SERVER_CLAN_MEMBERNEWCHIEFREPLY"; case SERVER_CLAN_CLANACK: return "SERVER_CLAN_CLANACK"; case SERVER_CLANQUITNOTIFY: return "SERVER_CLANQUITNOTIFY"; case SERVER_CLAN_INVITEREPLY: return "SERVER_CLAN_INVITEREPLY"; case SERVER_CLANMEMBER_REMOVE_REPLY: return "SERVER_CLANMEMBER_REMOVE_REPLY"; case SERVER_CLAN_INVITEREQ: return "SERVER_CLAN_INVITEREQ"; case SERVER_CLANMEMBER_RANKUPDATE_REPLY: return "SERVER_CLANMEMBER_RANKUPDATE_REPLY"; case SERVER_CLAN_MOTDREPLY: return "SERVER_CLAN_MOTDREPLY"; case SERVER_CLANMEMBERLIST_REPLY: return "SERVER_CLANMEMBERLIST_REPLY"; case SERVER_CLANMEMBER_REMOVED_NOTIFY: return "SERVER_CLANMEMBER_REMOVED_NOTIFY"; case SERVER_CLANMEMBERUPDATE: return "SERVER_CLANMEMBERUPDATE"; } return "unknown"; case packet_class_file: if (packet_get_size(packet)<sizeof(t_file_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.file.h.type)) { case SERVER_FILE_REPLY: return "SERVER_FILE_REPLY"; } return "unknown"; case packet_class_udp: if (packet_get_size(packet)<sizeof(t_udp_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_int_get(packet->u.udp.h.type)) { case SERVER_UDPTEST: return "SERVER_UDPTEST"; } return "unknown"; case packet_class_raw: return "SERVER_RAW"; case packet_class_d2game: if (packet_get_size(packet)<sizeof(t_d2game_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_byte_get(packet->u.d2game.h.type)) { default: return "SERVER_D2GAME"; } return "unknown"; case packet_class_d2cs: return "D2CS"; case packet_class_d2gs: return "D2GS"; case packet_class_d2cs_bnetd: return "D2CS_BNETD"; case packet_class_w3route: if (packet_get_size(packet)<sizeof(t_w3route_header)) { eventlog(eventlog_level_error,__FUNCTION__,"packet is shorter than header (len=%u)",packet_get_size(packet)); return "unknown"; } switch (bn_short_get(packet->u.bnet.h.type)) { case SERVER_W3ROUTE_READY: return "SERVER_W3ROUTE_READY"; case SERVER_W3ROUTE_LOADINGACK: return "SERVER_W3ROUTE_LOADINGACK"; case SERVER_W3ROUTE_ECHOREQ: return "SERVER_W3ROUTE_ECHOREQ"; case SERVER_W3ROUTE_ACK: return "SERVER_W3ROUTE_ACK"; case SERVER_W3ROUTE_PLAYERINFO: return "SERVER_W3ROUTE_PLAYERINFO"; case SERVER_W3ROUTE_LEVELINFO: return "SERVER_W3ROUTE_LEVELINFO"; case SERVER_W3ROUTE_STARTGAME1: return "SERVER_W3ROUTE_STARTGAME1"; case SERVER_W3ROUTE_STARTGAME2: return "SERVER_W3ROUTE_STARTGAME2"; } return "unknown"; case packet_class_wolgameres: return "CLIENT_WOLGAMERES"; case packet_class_none: return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return "unknown"; } eventlog(eventlog_level_error,__FUNCTION__,"got unknown direction %d",(int)dir); return "unknown"; }
extern unsigned int packet_get_type(t_packet const * packet) { if (!packet) { eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet"); return 0; } switch (packet->pclass) { case packet_class_init: return CLIENT_INITCONN; /* all init packets are of this type */ case packet_class_bnet: if (packet_get_size(packet)<sizeof(t_bnet_header)) { eventlog(eventlog_level_error,__FUNCTION__,"bnet packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return (unsigned int)bn_short_get(packet->u.bnet.h.type); case packet_class_file: if (packet_get_size(packet)<sizeof(t_file_header)) { eventlog(eventlog_level_error,__FUNCTION__,"file packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return (unsigned int)bn_short_get(packet->u.file.h.type); case packet_class_udp: if (packet_get_size(packet)<sizeof(t_udp_header)) { eventlog(eventlog_level_error,__FUNCTION__,"udp packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_int_get(packet->u.udp.h.type); case packet_class_raw: return 0; /* raw packets don't have a type, but don't warn because the packet dump tries anyway */ case packet_class_d2game: if (packet_get_size(packet)<sizeof(t_d2game_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2game packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_byte_get(packet->u.d2game.h.type); case packet_class_d2gs: if (packet_get_size(packet)<sizeof(t_d2cs_d2gs_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2gs packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_short_get(packet->u.d2cs_d2gs.h.type); case packet_class_d2cs_bnetd: if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs_bnetd packet shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_short_get(packet->u.d2cs_d2gs.h.type); case packet_class_d2cs: if (packet_get_size(packet)<sizeof(t_d2cs_client_header)) { eventlog(eventlog_level_error,__FUNCTION__,"d2cs packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_byte_get(packet->u.d2cs_client.h.type); case packet_class_w3route: if (packet_get_size(packet)<sizeof(t_w3route_header)) { eventlog(eventlog_level_error,__FUNCTION__,"w3route packet is shorter than header (len=%u)",packet_get_size(packet)); return 0; } return bn_short_get(packet->u.w3route.h.type); case packet_class_wolgameres: return 0; /* wolgameres packets don't have a type */ default: eventlog(eventlog_level_error,__FUNCTION__,"packet has invalid class %d",(int)packet->pclass); return 0; } }
static int on_client_creategamereq(t_connection * c, t_packet * packet) { char const * gamename; char const * gamepass; char const * gamedesc; t_game * game; t_d2gs * gs; t_gq * gq; unsigned int tempflag,gameflag; unsigned int leveldiff, maxchar, difficulty, expansion, hardcore, ladder; unsigned int seqno, reply; unsigned int pos; t_elem * elem; pos=sizeof(t_client_d2cs_creategamereq); if (!(gamename=packet_get_str_const(packet,pos,MAX_GAMENAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game name"); return -1; } pos+=std::strlen(gamename)+1; if (!(gamepass=packet_get_str_const(packet,pos,MAX_GAMEPASS_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game pass"); return -1; } pos+=std::strlen(gamepass)+1; if (!(gamedesc=packet_get_str_const(packet,pos,MAX_GAMEDESC_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad game desc"); return -1; } tempflag=bn_int_get(packet->u.client_d2cs_creategamereq.gameflag); leveldiff=bn_byte_get(packet->u.client_d2cs_creategamereq.leveldiff); maxchar=bn_byte_get(packet->u.client_d2cs_creategamereq.maxchar); difficulty=gameflag_get_difficulty(tempflag); if (difficulty > conn_get_charinfo_difficulty(c)) { eventlog(eventlog_level_error,__FUNCTION__,"game difficulty exceed character limit %d %d",difficulty, conn_get_charinfo_difficulty(c)); return 0; } expansion=conn_get_charinfo_expansion(c); hardcore=conn_get_charinfo_hardcore(c); ladder=conn_get_charinfo_ladder(c); gameflag=gameflag_create(ladder,expansion,hardcore,difficulty); gs = NULL; game = NULL; gq=conn_get_gamequeue(c); if (d2cs_gamelist_find_game(gamename)) { eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in gamelist",gamename); reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else if (!gq && gqlist_find_game(gamename)) { eventlog(eventlog_level_info,__FUNCTION__,"game name %s is already exist in game queue",gamename); reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else if (!(gs=d2gslist_choose_server())) { if (gq) { eventlog(eventlog_level_error,__FUNCTION__,"client %d is already in game queue",d2cs_conn_get_sessionnum(c)); conn_set_gamequeue(c,NULL); gq_destroy(gq,&elem); return 0; } else if ((gq=gq_create(d2cs_conn_get_sessionnum(c), packet, gamename))) { conn_set_gamequeue(c,gq); d2cs_send_client_creategamewait(c,gqlist_get_length()); return 0; } reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } else if (hardcore && conn_get_charinfo_dead(c)) { reply=D2CS_CLIENT_CREATEGAMEREPLY_FAILED; } else if (!(game=d2cs_game_create(gamename,gamepass,gamedesc,gameflag))) { reply=D2CS_CLIENT_CREATEGAMEREPLY_NAME_EXIST; } else { reply=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED; game_set_d2gs(game,gs); d2gs_add_gamenum(gs, 1); game_set_gameflag_ladder(game,ladder); game_set_gameflag_expansion(game,expansion); game_set_created(game,0); game_set_leveldiff(game,leveldiff); game_set_charlevel(game,conn_get_charinfo_level(c)); game_set_maxchar(game,maxchar); game_set_gameflag_difficulty(game,difficulty); game_set_gameflag_hardcore(game,hardcore); } seqno=bn_short_get(packet->u.client_d2cs_creategamereq.seqno); if (reply!=D2CS_CLIENT_CREATEGAMEREPLY_SUCCEED) { t_packet * rpacket; if ((rpacket=packet_create(packet_class_d2cs))) { packet_set_size(rpacket,sizeof(t_d2cs_client_creategamereply)); packet_set_type(rpacket,D2CS_CLIENT_CREATEGAMEREPLY); bn_short_set(&rpacket->u.d2cs_client_creategamereply.seqno,seqno); bn_short_set(&rpacket->u.d2cs_client_creategamereply.u1,0); bn_short_set(&rpacket->u.d2cs_client_creategamereply.gameid,0); bn_int_set(&rpacket->u.d2cs_client_creategamereply.reply,reply); conn_push_outqueue(c,rpacket); packet_del_ref(rpacket); } } else { t_packet * gspacket; t_sq * sq; struct in_addr addr; if ((gspacket=packet_create(packet_class_d2gs))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,d2cs_game_get_id(game)))) { packet_set_size(gspacket,sizeof(t_d2cs_d2gs_creategamereq)); packet_set_type(gspacket,D2CS_D2GS_CREATEGAMEREQ); bn_int_set(&gspacket->u.d2cs_d2gs_creategamereq.h.seqno,sq_get_seqno(sq)); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.difficulty,difficulty); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.hardcore,hardcore); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.expansion,expansion); bn_byte_set(&gspacket->u.d2cs_d2gs_creategamereq.ladder,ladder); packet_append_string(gspacket,gamename); packet_append_string(gspacket,gamepass); packet_append_string(gspacket,gamedesc); packet_append_string(gspacket,d2cs_conn_get_account(c)); packet_append_string(gspacket,d2cs_conn_get_charname(c)); addr.s_addr = htonl(d2cs_conn_get_addr(c)); packet_append_string(gspacket,inet_ntoa(addr)); conn_push_outqueue(d2gs_get_connection(gs),gspacket); } packet_del_ref(gspacket); eventlog(eventlog_level_info,__FUNCTION__,"request create game %s on gs %d",gamename,d2gs_get_id(gs)); } } return 0; }
int d2ladder_readladder(void) { t_d2ladder * d2ladder; t_d2ladderfile_header fileheader; std::FILE * fdladder; t_d2ladderfile_ladderindex * lhead; t_d2ladderfile_ladderinfo * ldata; t_d2ladder_info * info; t_d2ladder_info temp; long leftsize,blocksize; unsigned int laddertype; unsigned int tempmaxtype; int readlen; unsigned int i, number; if (!d2ladder_ladder_file) return -1; fdladder=std::fopen(d2ladder_ladder_file,"rb"); if(!fdladder) { eventlog(eventlog_level_error,__FUNCTION__,"canot open ladder file"); return -1; } std::fseek(fdladder,0,SEEK_END); leftsize=std::ftell(fdladder); std::rewind(fdladder); blocksize=sizeof(fileheader) ; if (leftsize<blocksize) { eventlog(eventlog_level_error,__FUNCTION__,"file size error"); std::fclose(fdladder); return -1; } readlen=std::fread(&fileheader,1,sizeof(fileheader),fdladder); if (readlen<=0) { eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,std::strerror(errno)); std::fclose(fdladder); return -1; } tempmaxtype=bn_int_get(fileheader.maxtype); leftsize-=blocksize; if(tempmaxtype>D2LADDER_MAXTYPE) { eventlog(eventlog_level_error,__FUNCTION__,"ladder type > D2LADDER_MAXTYPE error"); std::fclose(fdladder); return -1; } d2ladder_maxtype=tempmaxtype; blocksize=d2ladder_maxtype*sizeof(*lhead); if (leftsize < blocksize ) { eventlog(eventlog_level_error,__FUNCTION__,"file size error"); std::fclose(fdladder); return -1; } lhead=(t_d2ladderfile_ladderindex*)xmalloc(blocksize); readlen=std::fread(lhead,1,d2ladder_maxtype*sizeof(*lhead),fdladder); if (readlen<=0) { eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,std::strerror(errno)); xfree(lhead); std::fclose(fdladder); return -1; } leftsize-=blocksize; blocksize=0; for(i=0;i<d2ladder_maxtype;i++) { blocksize+=bn_int_get(lhead[i].number)*sizeof(*ldata); } if (leftsize < blocksize ) { eventlog(eventlog_level_error,__FUNCTION__,"file size error"); xfree(lhead); std::fclose(fdladder); return -1; } for(laddertype=0;laddertype<d2ladder_maxtype;laddertype++) { number= bn_int_get(lhead[laddertype].number); if(number<=0) continue; d2ladder=d2ladderlist_find_type(laddertype); if (!d2ladder) { eventlog(eventlog_level_error,__FUNCTION__,"could not find ladder type %d",laddertype); continue; } ldata=(t_d2ladderfile_ladderinfo*)xmalloc(number*sizeof(*ldata)); info=(t_d2ladder_info*)xmalloc(number * sizeof(*info)); std::memset(info,0,number * sizeof(*info)); std::fseek(fdladder,bn_int_get(lhead[laddertype].offset),SEEK_SET); readlen=std::fread(ldata,1,number*sizeof(*ldata),fdladder); if (readlen<=0) { eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,std::strerror(errno)); xfree(ldata); xfree(info); continue; } d2ladder->info=info; d2ladder->len=number; for (i=0; i< number; i++) { if (!ldata[i].charname[0]) continue; temp.experience=bn_int_get(ldata[i].experience); temp.status=bn_short_get(ldata[i].status); temp.level=bn_byte_get(ldata[i].level); temp.chclass=bn_byte_get(ldata[i].chclass); std::strncpy(temp.charname,ldata[i].charname,sizeof(info[i].charname)); if (d2ladder_update_info_and_pos(d2ladder,&temp, d2ladder_find_char_all(d2ladder,&temp), d2ladder_find_pos(d2ladder,&temp))==1) { d2ladder_change_count++; } } xfree(ldata); } leftsize-=blocksize; xfree(lhead); std::fclose(fdladder); return 0; }
extern int d2charinfo_load(char const * account, char const * charname, t_d2charinfo_file * data) { char * file; int size, ladder_time; if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); size=sizeof(t_d2charinfo_file); if (file_read(file,data,&size)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading character file %s",file); xfree(file); return -1; } if (size!=sizeof(t_d2charinfo_file)) { eventlog(eventlog_level_error,__FUNCTION__,"got bad charinfo file %s (length %d)",charname,size); xfree(file); return -1; } d2char_portrait_init(&data->portrait); if (d2charinfo_check(data) < 0) { xfree(file); return -1; } if (!(charstatus_get_ladder(bn_int_get(data->summary.charstatus)))) { bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); xfree(file); return 0; } ladder_time = prefs_get_ladder_start_time(); if ((ladder_time > 0) && bn_int_get(data->header.create_time) < ladder_time) { char buffer[MAX_SAVEFILE_SIZE]; unsigned int status_offset; unsigned char status; unsigned int charstatus; unsigned int size; unsigned int version; unsigned int checksum; FILE * fp; eventlog(eventlog_level_info,__FUNCTION__,"%s(*%s) was created in old ladder season, set to non-ladder", charname, account); if (!(fp=fopen(file,"wb"))) { eventlog(eventlog_level_error,__FUNCTION__,"charinfo file \"%s\" does not exist for account \"%s\"",file,account); xfree(file); return 0; } xfree(file); charstatus = bn_int_get(data->summary.charstatus); charstatus_set_ladder(charstatus, 0); bn_int_set(&data->summary.charstatus, charstatus); status=bn_byte_get(data->portrait.status); charstatus_set_ladder(status,0); bn_byte_set(&data->portrait.status,status); bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); if (fwrite(data,1,sizeof(*data),fp)!=sizeof(*data)) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } fclose(fp); file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return 0; } xfree(file); size=fread(buffer,1,sizeof(buffer),fp); if (!feof(fp)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET); if (version>=0x5C) { status_offset=D2CHARSAVE_STATUS_OFFSET_109; } else { status_offset=D2CHARSAVE_STATUS_OFFSET; } status=bn_byte_get(buffer+status_offset); charstatus_set_ladder(status,0); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ bn_byte_set((bn_byte *)(buffer+status_offset),status); if (version>=0x5C) { checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET); bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); } fseek(fp,0,SEEK_SET); if (fwrite(buffer,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } fclose(fp); } else { bn_byte_set(&data->portrait.ladder, 1); xfree(file); } return 0; }
extern int d2char_convert(char const * account, char const * charname) { FILE * fp; char * file; unsigned char buffer[MAX_SAVEFILE_SIZE]; unsigned int status_offset; unsigned char status; unsigned int charstatus; t_d2charinfo_file charinfo; unsigned int size; unsigned int version; unsigned int checksum; ASSERT(account,-1); ASSERT(charname,-1); /* Playing with a expanstion char on a classic realm will cause the game server to crash, therefore I recommed setting allow_convert = 0 in the d2cs.conf We need to do this to prevent creating classic char and converting to expantion on a classic realm. LOD Char must be created on LOD realm */ if (!prefs_get_allow_convert()) { eventlog(eventlog_level_info,__FUNCTION__,"Convert char has been disabled"); return -1; } /* Procedure is stopped here and returned if allow_convet = 0 in d2cs.conf */ if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open charinfo file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); if (fread(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charinfo file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } charstatus=bn_int_get(charinfo.summary.charstatus); charstatus_set_expansion(charstatus,1); bn_int_set(&charinfo.summary.charstatus,charstatus); status=bn_byte_get(charinfo.portrait.status); charstatus_set_expansion(status,1); bn_byte_set(&charinfo.portrait.status,status); fseek(fp,0,SEEK_SET); /* FIXME: check return */ if (fwrite(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close charinfo file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno)); return -1; } file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); size=fread(buffer,1,sizeof(buffer),fp); if (!feof(fp)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET); if (version>=0x0000005C) { status_offset=D2CHARSAVE_STATUS_OFFSET_109; } else { status_offset=D2CHARSAVE_STATUS_OFFSET; } status=bn_byte_get(buffer+status_offset); charstatus_set_expansion(status,1); bn_byte_set((bn_byte *)(buffer+status_offset),status); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ if (version>=0x0000005C) { checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET); bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ } fseek(fp,0,SEEK_SET); /* FIXME: check return */ if (fwrite(buffer,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close charsave file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno)); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) converted to expansion",charname,account); return 0; }