Beispiel #1
0
extern int send_d2cs_gameinforeq(t_connection * c)
{
	t_packet	* packet;
	t_game		* game;
	t_realm		* realm;

	if (!(c))
	{
		eventlog(eventlog_level_error,__FUNCTION__,"got NULL conn");
		return -1;
	}
	
	if (!(game = conn_get_game(c)))
	{
		eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL game");
		return -1;
	}

	if (!(realm = conn_get_realm(c)))
	{
		eventlog(eventlog_level_error,__FUNCTION__,"conn had NULL realm");
		return -1;
	}


	if ((packet=packet_create(packet_class_d2cs_bnetd))) {
		packet_set_size(packet,sizeof(t_bnetd_d2cs_gameinforeq));
		packet_set_type(packet,BNETD_D2CS_GAMEINFOREQ);
		bn_int_set(&packet->u.bnetd_d2cs_gameinforeq.h.seqno,0);
		packet_append_string(packet,game_get_name(game));
		conn_push_outqueue(realm_get_conn(realm),packet);
		packet_del_ref(packet);
	}
	return 0;
}
Beispiel #2
0
Datei: irc.c Projekt: 91D2/pvpgn
extern int irc_send_ping(t_connection * conn)
{
    t_packet * p;
    char data[MAX_IRC_MESSAGE_LEN];
    
    if (!conn) {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
	return -1;
    }
    if (!(p = packet_create(packet_class_raw))) {
	eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
	return -1;
    }

    if((conn_get_wol(conn) == 1))
        return 0;

    conn_set_ircping(conn,get_ticks());
    if (conn_get_state(conn)==conn_state_bot_username)
    	sprintf(data,"PING :%u\r\n",conn_get_ircping(conn)); /* Undernet doesn't reveal the servername yet ... neither do we */
    else if ((6+strlen(server_get_hostname())+2+1)<=MAX_IRC_MESSAGE_LEN)
    	sprintf(data,"PING :%s\r\n",server_get_hostname());
    else
    	eventlog(eventlog_level_error,__FUNCTION__,"maximum message length exceeded");
    eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data);
    packet_set_size(p,0);
    packet_append_data(p,data,strlen(data));
    conn_push_outqueue(conn,p);
    packet_del_ref(p);
    return 0;
}
Beispiel #3
0
Datei: irc.c Projekt: 91D2/pvpgn
extern int irc_send_pong(t_connection * conn, char const * params)
{
    t_packet * p;
    char data[MAX_IRC_MESSAGE_LEN];
    
    if (!conn) {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
	return -1;
    }
    if ((1+strlen(server_get_hostname())+1+4+1+strlen(server_get_hostname())+((params)?(2+strlen(params)):(0))+2+1) > MAX_IRC_MESSAGE_LEN) {
	eventlog(eventlog_level_error,__FUNCTION__,"max message length exceeded");
	return -1;
    }
    if (!(p = packet_create(packet_class_raw))) {
	eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
	return -1;
    }
    
    if (params)
    	sprintf(data,":%s PONG %s :%s\r\n",server_get_hostname(),server_get_hostname(),params);
    else
    	sprintf(data,":%s PONG %s\r\n",server_get_hostname(),server_get_hostname());
    eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data);
    packet_set_size(p,0);
    packet_append_data(p,data,strlen(data));
    conn_push_outqueue(conn,p);
    packet_del_ref(p);
    return 0;
}
Beispiel #4
0
extern int packet_append_ntstring(t_packet * packet, char const * str)
{
    unsigned int   len;
    unsigned short addlen;
    unsigned short size;

    if (!packet)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"got NULL packet");
        return -1;
    }
    if (!str)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"got NULL string");
        return -1;
    }

    len = std::strlen(str);
    size = packet_get_size(packet);
    if (size>=MAX_PACKET_SIZE)
        return -1;

    if (MAX_PACKET_SIZE-(unsigned int)size>len)
	    addlen = len;
    else
	    addlen = MAX_PACKET_SIZE-size;
    if (addlen<1)
	return -1;

    std::memcpy(packet->u.data+size,str,addlen);
    packet_set_size(packet,size+addlen);

    return (int)addlen;
}
Beispiel #5
0
static int on_d2cs_authreply(t_connection * c, t_packet const * packet)
{
	t_packet	* rpacket;
	unsigned int	version;
	unsigned int	try_version;
	unsigned int	reply;
	char const	* realmname;
	t_realm		* realm;

	if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_authreply)) {
		eventlog(eventlog_level_error,__FUNCTION__,"got bad packet size");
		return -1;
	}
	if (!(realmname=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_authreply),REALM_NAME_LEN))) {
		eventlog(eventlog_level_error,__FUNCTION__,"got bad realmname");
		return -1;
	}
        if (!(realm=realmlist_find_realm(realmname))) {
		realm=realmlist_find_realm_by_ip(conn_get_addr(c)); /* should not fail - checked in handle_init_packet() handle_init.c */
		eventlog(eventlog_level_warn,__FUNCTION__, "warn: realm name mismatch %s %s", realm_get_name(realm), realmname);
		if (!(prefs_allow_d2cs_setname())) { /* fail if allow_d2cs_setname = false */
			eventlog(eventlog_level_error,__FUNCTION__, "d2cs not allowed to set realm name");
			return -1;
		}
		if (realm_get_active(realm)) { /* fail if realm already active */
			eventlog(eventlog_level_error,__FUNCTION__, "cannot set realm name to %s (realm already active)",realmname);
			return -1;
		}
		realm_set_name(realm,realmname);
        }
	version=prefs_get_d2cs_version();
	try_version=bn_int_get(packet->u.d2cs_bnetd_authreply.version);
	if (version && version != try_version) {
		eventlog(eventlog_level_error,__FUNCTION__,"d2cs version mismatch 0x%X - 0x%X",
			try_version,version);
		reply=BNETD_D2CS_AUTHREPLY_BAD_VERSION;
	} else {
		reply=BNETD_D2CS_AUTHREPLY_SUCCEED;
	}

	if (reply==BNETD_D2CS_AUTHREPLY_SUCCEED) {
		eventlog(eventlog_level_info,__FUNCTION__,"d2cs %s authed",
			addr_num_to_ip_str(conn_get_addr(c)));
		conn_set_state(c,conn_state_loggedin);
		realm_active(realm,c);
	} else {
		eventlog(eventlog_level_error,__FUNCTION__,"failed to auth d2cs %s",
			addr_num_to_ip_str(conn_get_addr(c)));
	}
	if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
		packet_set_size(rpacket,sizeof(t_bnetd_d2cs_authreply));
		packet_set_type(rpacket,BNETD_D2CS_AUTHREPLY);
		bn_int_set(&rpacket->u.bnetd_d2cs_authreply.h.seqno,1);
		bn_int_set(&rpacket->u.bnetd_d2cs_authreply.reply,reply);
		conn_push_outqueue(c,rpacket);
		packet_del_ref(rpacket);
	}
	return 0;
}
Beispiel #6
0
static int on_d2cs_authreply(t_connection * c, t_packet const * packet)
{
	t_packet	* rpacket;
	unsigned int	version;
	unsigned int	try_version;
	unsigned int	reply;
	char const	* realmname;
	t_realm		* realm;

	if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_authreply)) {
		eventlog(eventlog_level_error,"on_d2cs_authreply","got bad packet size");
		return -1;
	}
	if (!(realmname=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_authreply),REALM_NAME_LEN))) {
		eventlog(eventlog_level_error,"on_d2cs_authreply","got bad realmname");
		return -1;
	}
        if (!(realm=realmlist_find_realm_by_ip(conn_get_addr(c)))) {
                eventlog(eventlog_level_error,"handle_init_packet", "realm not found");
                return -1;
        }
	if (realm_get_name(realm) && strcasecmp(realmname,realm_get_name(realm))) {
                eventlog(eventlog_level_error,"handle_init_packet", "warn: realm name mismatch %s %s",
			realm_get_name(realm),realmname);
	}

	version=prefs_get_d2cs_version();
	try_version=bn_int_get(packet->u.d2cs_bnetd_authreply.version);
	if (version && version != try_version) {
		eventlog(eventlog_level_error,"on_d2cs_authreply","d2cs version mismatch 0x%X - 0x%X",
			try_version,version);
		reply=BNETD_D2CS_AUTHREPLY_BAD_VERSION;
	} else {
		reply=BNETD_D2CS_AUTHREPLY_SUCCEED;
	}

	if (reply==BNETD_D2CS_AUTHREPLY_SUCCEED) {
		eventlog(eventlog_level_error,"on_d2cs_authreply","d2cs %s authed",
			addr_num_to_ip_str(conn_get_addr(c)));
		conn_set_state(c,conn_state_loggedin);
		if (prefs_allow_d2cs_setname()) realm_set_name(realm,realmname);
		realm_active(realm,c);
	} else {
		eventlog(eventlog_level_error,"on_d2cs_authreply","failed to auth d2cs %s",
			addr_num_to_ip_str(conn_get_addr(c)));
	}
	if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
		packet_set_size(rpacket,sizeof(t_bnetd_d2cs_authreply));
		packet_set_type(rpacket,BNETD_D2CS_AUTHREPLY);
		bn_int_set(&rpacket->u.bnetd_d2cs_authreply.reply,reply);
		queue_push_packet(conn_get_out_queue(c),rpacket);
		packet_del_ref(rpacket);
	}
	return 0;
}
static int on_client_gameinforeq(t_connection * c, t_packet * packet)
{
	t_game_charinfo	* info;
	t_packet	* rpacket;
	char const	* gamename;
	t_game		* game;
	unsigned int	seqno, n;

	if (!(gamename=packet_get_str_const(packet,sizeof(t_client_d2cs_gameinforeq),MAX_GAMENAME_LEN))) {
		eventlog(eventlog_level_error,__FUNCTION__,"got bad game name");
		return -1;
	}
	if (!(game=d2cs_gamelist_find_game(gamename))) {
		eventlog(eventlog_level_error,__FUNCTION__,"game %s not found",gamename);
		return 0;
	}
	seqno=bn_short_get(packet->u.client_d2cs_gameinforeq.seqno);
	if ((rpacket=packet_create(packet_class_d2cs))) {
		packet_set_size(rpacket,sizeof(t_d2cs_client_gameinforeply));
		packet_set_type(rpacket,D2CS_CLIENT_GAMEINFOREPLY);
		bn_short_set(&rpacket->u.d2cs_client_gameinforeply.seqno,seqno);
		bn_int_set(&rpacket->u.d2cs_client_gameinforeply.gameflag,game_get_gameflag(game));
		bn_int_set(&rpacket->u.d2cs_client_gameinforeply.etime,std::time(NULL)-d2cs_game_get_create_time(game));
		bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.charlevel,game_get_charlevel(game));
		bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.leveldiff,game_get_leveldiff(game));
		bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.maxchar,game_get_maxchar(game));
		packet_append_string(rpacket, game_get_desc(game) ? game_get_desc(game) : NULL);

		n=0;
		BEGIN_LIST_TRAVERSE_DATA_CONST(game_get_charlist(game),info,t_game_charinfo)
		{
			if (!info->charname) {
				eventlog(eventlog_level_error,__FUNCTION__,"got NULL charname in game %s char list",gamename);
				continue;
			}
			packet_append_string(rpacket,info->charname);
			bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.chclass[n],info->chclass);
			/* GUI is limited to a max level of 255 */
			if (info->level < 255) {
			bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.level[n],info->level);
			} else {
				bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.level[n], 255);
			}
			n++;
		}
		END_LIST_TRAVERSE_DATA_CONST()

		bn_byte_set(&rpacket->u.d2cs_client_gameinforeply.currchar,n);
		if (n!=game_get_currchar(game)) {
			eventlog(eventlog_level_error,__FUNCTION__,"game %s character list corrupted",gamename);
		}
		conn_push_outqueue(c,rpacket);
		packet_del_ref(rpacket);
	}
Beispiel #8
0
Datei: irc.c Projekt: 91D2/pvpgn
extern int irc_send_cmd2(t_connection * conn, char const * prefix, char const * command, char const * postfix, char const * comment)
{
    t_packet * p;
    char data[MAX_IRC_MESSAGE_LEN+1];
    int len;
    
    if (!conn) {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
	return -1;
    }
    if (!prefix)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL prefix");
	return -1;
    }
    if (!command) {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL command");
	return -1;
    }
    if (!postfix)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL postfix");
	return -1;
    }
    
    if (!(p = packet_create(packet_class_raw))) {
	eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
	return -1;
    }

    if (comment) {
        len = 1+strlen(prefix)+1+strlen(command)+1+strlen(postfix)+2+strlen(comment)+1+2;
    	if (len > MAX_IRC_MESSAGE_LEN) {
	    eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len);
	    return -1;
	}
	else
	    sprintf(data,":%s %s %s :%s\r\n",prefix,command,postfix,comment);
    } else {
        len = 1+strlen(prefix)+1+strlen(command)+1+strlen(postfix)+1+2;
    	if (len > MAX_IRC_MESSAGE_LEN) {
	    eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len);
	    return -1;
	}
	else
	sprintf(data,":%s %s %s\r\n",prefix,command,postfix);
    }
    packet_set_size(p,0);
    packet_append_data(p,data,len);
    // eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data);
    conn_push_outqueue(conn,p);
    packet_del_ref(p);
    return 0;
}
Beispiel #9
0
extern int udptest_send(t_connection const * c)
{
    t_packet *         upacket;
    struct sockaddr_in caddr;
    unsigned int       tries,successes;

    memset(&caddr,0,sizeof(caddr));
    caddr.sin_family = PSOCK_AF_INET;
    caddr.sin_port = htons(conn_get_game_port(c));
    caddr.sin_addr.s_addr = htonl(conn_get_game_addr(c));

    for (tries=successes=0; successes!=2 && tries<5; tries++)
    {
        if (!(upacket = packet_create(packet_class_udp)))
        {
            eventlog(eventlog_level_error,"udptest_send","[%d] could not allocate memory for packet",conn_get_socket(c));
            continue;
        }
        packet_set_size(upacket,sizeof(t_server_udptest));
        packet_set_type(upacket,SERVER_UDPTEST);
        bn_int_tag_set(&upacket->u.server_udptest.bnettag,BNETTAG);

        if (hexstrm)
        {
            fprintf(hexstrm,"%d: send class=%s[0x%02hx] type=%s[0x%04hx] ",
                    conn_get_game_socket(c),
                    packet_get_class_str(upacket),(unsigned int)packet_get_class(upacket),
                    packet_get_type_str(upacket,packet_dir_from_server),packet_get_type(upacket));
            fprintf(hexstrm,"from=%s ",
                    addr_num_to_addr_str(conn_get_game_addr(c),conn_get_game_port(c)));
            fprintf(hexstrm,"to=%s ",
                    addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)));
            fprintf(hexstrm,"length=%u\n",
                    packet_get_size(upacket));
            hexdump(hexstrm,packet_get_raw_data(upacket,0),packet_get_size(upacket));
        }

        if (psock_sendto(conn_get_game_socket(c),
                         packet_get_raw_data_const(upacket,0),packet_get_size(upacket),
                         0,(struct sockaddr *)&caddr,(psock_t_socklen)sizeof(caddr))!=(int)packet_get_size(upacket))
            eventlog(eventlog_level_error,"udptest_send","[%d] failed to send UDPTEST to %s (attempt %u) (psock_sendto: %s)",conn_get_socket(c),addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),conn_get_game_port(c)),tries+1,strerror(psock_errno()));
        else
            successes++;

        packet_del_ref(upacket);
    }

    if (successes!=2)
        return -1;

    return 0;
}
Beispiel #10
0
Datei: irc.c Projekt: 91D2/pvpgn
extern int irc_send_cmd(t_connection * conn, char const * command, char const * params)
{
    t_packet * p;
    char data[MAX_IRC_MESSAGE_LEN+1];
    int len;
    char const * ircname = server_get_hostname(); 
    char const * nick;
    
    if (!conn) {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
	return -1;
    }
    if (!command) {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL command");
	return -1;
    }
    if (!(p = packet_create(packet_class_raw))) {
	eventlog(eventlog_level_error,__FUNCTION__,"could not create packet");
	return -1;
    }

    nick = conn_get_loggeduser(conn);
    if (!nick)
    	nick = "";
    	
    /* snprintf isn't portable -> check message length first */
    if (params) {
        len = 1+strlen(ircname)+1+strlen(command)+1+strlen(nick)+1+strlen(params)+2;
	if (len > MAX_IRC_MESSAGE_LEN) {
	    eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len);
	    return -1;
	}
	else
	    sprintf(data,":%s %s %s %s\r\n",ircname,command,nick,params);
    } else {
        len = 1+strlen(ircname)+1+strlen(command)+1+strlen(nick)+1+2;
    	if (len > MAX_IRC_MESSAGE_LEN) {
	    eventlog(eventlog_level_error,__FUNCTION__,"message to send is too large (%d bytes)",len);
	    return -1;
	}
	else
	sprintf(data,":%s %s %s\r\n",ircname,command,nick);
    }
    packet_set_size(p,0);
    packet_append_data(p,data,len);
    // eventlog(eventlog_level_debug,__FUNCTION__,"[%d] sent \"%s\"",conn_get_socket(conn),data);
    conn_push_outqueue(conn,p);
    packet_del_ref(p);
    return 0;
}
Beispiel #11
0
static int on_bnetd_accountloginreply(t_connection * c, t_packet * packet)
{
	unsigned int	seqno;
	t_sq		* sq;
	t_packet	* opacket, * rpacket;
	t_connection	* client;
	int		result, reply;
	char const	* account;
	t_elem		* elem;

	if (!packet || !c)
	    return -1;

	seqno=bn_int_get(packet->u.d2cs_bnetd.h.seqno);
	if (!(sq=sqlist_find_sq(seqno))) {
		eventlog(eventlog_level_error,__FUNCTION__,"seqno %d not found",seqno);
		return -1;
	}
	if (!(client=d2cs_connlist_find_connection_by_sessionnum(sq_get_clientid(sq)))) {
		eventlog(eventlog_level_error,__FUNCTION__,"client %d not found",sq_get_clientid(sq));
		sq_destroy(sq,&elem);
		return -1;
	}
	if (!(opacket=sq_get_packet(sq))) {
		eventlog(eventlog_level_error,__FUNCTION__,"previous packet missing (seqno: %d)",seqno);
		sq_destroy(sq,&elem);
		return -1;
	}
	result=bn_int_get(packet->u.bnetd_d2cs_accountloginreply.reply);
	if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) {
		reply=D2CS_CLIENT_LOGINREPLY_SUCCEED;
		account=packet_get_str_const(opacket,sizeof(t_client_d2cs_loginreq),MAX_CHARNAME_LEN);
		d2cs_conn_set_account(client,account);
		d2cs_conn_set_state(client,conn_state_authed);
		eventlog(eventlog_level_info,__FUNCTION__,"account %s authed",account);
	} else {
		eventlog(eventlog_level_warn,__FUNCTION__,"client %d login request was rejected by bnetd",sq_get_clientid(sq));
		reply=D2CS_CLIENT_LOGINREPLY_BADPASS;
	}
	if ((rpacket=packet_create(packet_class_d2cs))) {
		packet_set_size(rpacket,sizeof(t_d2cs_client_loginreply));
		packet_set_type(rpacket,D2CS_CLIENT_LOGINREPLY);
		bn_int_set(&rpacket->u.d2cs_client_loginreply.reply,reply);
		conn_push_outqueue(client,rpacket);
		packet_del_ref(rpacket);
	}
	sq_destroy(sq,&elem);
	return 0;
}
Beispiel #12
0
extern int handle_d2cs_init(t_connection * c)
{
	t_packet	* packet;

	if ((packet=packet_create(packet_class_d2cs_bnetd))) {
		packet_set_size(packet,sizeof(t_bnetd_d2cs_authreq));
		packet_set_type(packet,BNETD_D2CS_AUTHREQ);
		bn_int_set(&packet->u.bnetd_d2cs_authreq.sessionnum,conn_get_sessionnum(c));
		queue_push_packet(conn_get_out_queue(c),packet);
		packet_del_ref(packet);
	}
	eventlog(eventlog_level_info,"handle_d2cs_init","sent init packet to d2cs (sessionnum=%d)",
		conn_get_sessionnum(c));
	return 0;
}
Beispiel #13
0
static int on_bnetd_authreq(t_connection * c, t_packet * packet)
{
	t_packet	* rpacket;
	unsigned int	sessionnum;

	sessionnum=bn_int_get(packet->u.bnetd_d2cs_authreq.sessionnum);
	eventlog(eventlog_level_info,__FUNCTION__,"received bnetd sessionnum %d",sessionnum);
	if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
		packet_set_size(rpacket,sizeof(t_d2cs_bnetd_authreply));
		packet_set_type(rpacket,D2CS_BNETD_AUTHREPLY);
		bn_int_set(&rpacket->u.d2cs_bnetd_authreply.h.seqno,1);
		bn_int_set(&rpacket->u.d2cs_bnetd_authreply.version,D2CS_VERSION_NUMBER);
		packet_append_string(rpacket,prefs_get_realmname());
		conn_push_outqueue(c,rpacket);
		packet_del_ref(rpacket);
	}
	return 0;
}
Beispiel #14
0
extern int bits_va_lock_account(const char *name) {
	t_account * ac;
	t_packet * p;
	t_query * q;
	
	if (!name) {
		eventlog(eventlog_level_error,"bits_va_lock_account","got NULL name");
		return -1;
	}
	if ((ac = accountlist_find_account(name))) {
		if (account_get_bits_state(ac)!=account_state_unknown) {
			eventlog(eventlog_level_warn,"bits_va_lock_account","tried to lock an account which is already locked");
			return 0;
		}
	} else {
		/* create a dummy account */
		ac = create_vaccount(name,0);
		if (!ac) {
			eventlog(eventlog_level_error,"bits_va_lock_account","could not create dummy vaccount");
			return -1;
		}
	}
	p = packet_create(packet_class_bits);
	packet_set_size(p, sizeof(t_bits_va_lock));
	packet_set_type(p, BITS_VA_LOCK);
	bits_packet_generic(p, BITS_ADDR_PEER);
	q = query_create(bits_query_type_bits_va_lock);
	if (!q) {
		eventlog(eventlog_level_error,"bits_va_lock_account","bits_query_push failed.");
		packet_destroy(p);
		return -1;
	}
	/*bits_query_set_processed(q,-1);*/
	bn_int_set(&p->u.bits_va_lock.qid,q->qid);
	packet_append_string(p,name);
	query_attach_account(q,"account",ac);
	send_bits_packet_up(p);
	packet_del_ref(p);
	account_set_bits_state(ac,account_state_pending); /* request sent */
	accountlist_add_account(ac);
	return 0;
}
Beispiel #15
0
static int on_client_loginreq(t_connection * c, t_packet * packet)
{
	t_packet	* bnpacket;
	char const	* account;
	t_sq		* sq;
	unsigned int	sessionnum;

	if (!(account=packet_get_str_const(packet,sizeof(t_client_d2cs_loginreq),MAX_CHARNAME_LEN))) {
		eventlog(eventlog_level_error,__FUNCTION__,"got bad account name");
		return -1;
	}
	if (d2char_check_acctname(account)<0) {
		eventlog(eventlog_level_error,__FUNCTION__,"got bad account name");
		return -1;
	}
	if (!bnetd_conn()) {
		eventlog(eventlog_level_warn,__FUNCTION__,"d2cs is offline with bnetd, login request will be rejected");
		return -1;
	}
	sessionnum=bn_int_get(packet->u.client_d2cs_loginreq.sessionnum);
	conn_set_bnetd_sessionnum(c,sessionnum);
	eventlog(eventlog_level_info,__FUNCTION__,"got client (*%s) login request sessionnum=0x%X",account,sessionnum);
	if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) {
		if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) {
			packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_accountloginreq));
			packet_set_type(bnpacket,D2CS_BNETD_ACCOUNTLOGINREQ);
			bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.h.seqno,sq_get_seqno(sq));
			bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.seqno,
				bn_int_get(packet->u.client_d2cs_loginreq.seqno));
			bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionkey,
				bn_int_get(packet->u.client_d2cs_loginreq.sessionkey));
			bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionnum,sessionnum);
			memcpy(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash,
				packet->u.client_d2cs_loginreq.secret_hash,
				sizeof(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash));
			packet_append_string(bnpacket,account);
			conn_push_outqueue(bnetd_conn(),bnpacket);
		}
		packet_del_ref(bnpacket);
	}
	return 0;
}
Beispiel #16
0
extern int send_bits_gamelist_add_bits(t_connection * c, t_bits_game const * game)
{
    t_packet * p;

    if (!game) {
        eventlog(eventlog_level_error,"send_bits_gamelist_add_bits","got NULL game");
        return -1;
    }
    p = packet_create(packet_class_bits);
    if (!p) {
        eventlog(eventlog_level_error,"send_bits_gamelist_add_bits","could not create packet");
        return -1;
    }
    packet_set_size(p,sizeof(t_bits_gamelist_add));
    packet_set_type(p,BITS_GAMELIST_ADD);
    /***/
    bn_int_set(&p->u.bits_gamelist_add.id,game->id);
    bn_int_set(&p->u.bits_gamelist_add.type,game->type);
    bn_int_set(&p->u.bits_gamelist_add.status,game->status);
    /* convert the clienttag */
    memcpy(&p->u.bits_gamelist_add.clienttag,&game->clienttag,4);
    /* in case  game->owner  is unsigned int */
    bn_int_set(&p->u.bits_gamelist_add.owner,game->owner);
    /* append the strings */
    packet_append_string(p,game->name);
    packet_append_string(p,game->password);
    packet_append_string(p,game->info);
    /***/
    if (c) {
        /* send the packet on the connection */
        bits_packet_generic(p,BITS_ADDR_PEER);
        send_bits_packet_on(p,c);
    } else {
        /* broadcast the packet */
        bits_packet_generic(p,BITS_ADDR_BCAST);
        handle_bits_packet(bits_loopback_connection,p); /* also add the game on this server */
        send_bits_packet(p);
    }
    packet_del_ref(p);
    return 0;
}
		static int _client_anongame_cancel(t_connection * c)
		{
			t_packet * rpacket;
			t_connection * tc[ANONGAME_MAX_GAMECOUNT / 2];

			// [quetzal] 20020809 - added a_count, so we dont refer to already destroyed anongame
			t_anongame *a = conn_get_anongame(c);
			int a_count, i;

			eventlog(eventlog_level_info, __FUNCTION__, "[%d] got FINDANONGAME CANCEL packet", conn_get_socket(c));

			if (!a)
				return -1;

			a_count = anongame_get_count(a);

			// anongame_unqueue(c, anongame_get_queue(a));
			// -- already doing unqueue in conn_destroy_anongame
			for (i = 0; i < ANONGAME_MAX_GAMECOUNT / 2; i++)
				tc[i] = anongame_get_tc(a, i);

			for (i = 0; i < ANONGAME_MAX_GAMECOUNT / 2; i++) {
				if (tc[i] == NULL)
					continue;

				conn_set_routeconn(tc[i], NULL);
				conn_destroy_anongame(tc[i]);
			}

			if (!(rpacket = packet_create(packet_class_bnet)))
				return -1;

			packet_set_size(rpacket, sizeof(t_server_findanongame_playgame_cancel));
			packet_set_type(rpacket, SERVER_FINDANONGAME_PLAYGAME_CANCEL);
			bn_byte_set(&rpacket->u.server_findanongame_playgame_cancel.cancel, SERVER_FINDANONGAME_CANCEL);
			bn_int_set(&rpacket->u.server_findanongame_playgame_cancel.count, a_count);
			conn_push_outqueue(c, rpacket);
			packet_del_ref(rpacket);
			return 0;
		}
Beispiel #18
0
int on_bnetd_gameinforeq(t_connection * c, t_packet * packet)
{
	t_packet *    rpacket;
	t_game *      game;

	char const * gamename;

	if (!(c)) {
		eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
		return -1;
	}

	if (!(gamename = packet_get_str_const(packet,sizeof(t_bnetd_d2cs_gameinforeq),MAX_GAMENAME_LEN)))
	{
		eventlog(eventlog_level_error,__FUNCTION__,"missing or too long gamename");
		return -1;
	}

	if (!(game = d2cs_gamelist_find_game(gamename)))
	{
	       eventlog(eventlog_level_error,__FUNCTION__,"request for unknown game \"%s\"",gamename);
               return -1;
	}

	if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
		packet_set_size(rpacket, sizeof(t_d2cs_bnetd_gameinforeply));
		packet_set_type(rpacket, D2CS_BNETD_GAMEINFOREPLY);
		bn_int_set(&rpacket->u.d2cs_bnetd_gameinforeply.h.seqno,0);
		packet_append_string(rpacket, gamename);

		bn_byte_set(&rpacket->u.d2cs_bnetd_gameinforeply.difficulty, game_get_gameflag_difficulty(game));

		conn_push_outqueue(c,rpacket);
		packet_del_ref(rpacket);
	}
	return 0;
}
		/* tournament notice disabled at this time, but responce is sent to cleint */
		static int _client_anongame_tournament(t_connection * c, t_packet const * const packet)
		{
			t_packet * rpacket;

			t_account * account = conn_get_account(c);
			t_clienttag clienttag = conn_get_clienttag(c);

			unsigned int start_prelim = tournament_get_start_preliminary();
			unsigned int end_signup = tournament_get_end_signup();
			unsigned int end_prelim = tournament_get_end_preliminary();
			unsigned int start_r1 = tournament_get_start_round_1();

			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_anongame_tournament_reply));
			packet_set_type(rpacket, SERVER_FINDANONGAME_TOURNAMENT_REPLY);
			bn_byte_set(&rpacket->u.server_anongame_tournament_reply.option, 7);
			bn_int_set(&rpacket->u.server_anongame_tournament_reply.count,
				bn_int_get(packet->u.client_anongame_tournament_request.count));

			if (!start_prelim || (end_signup <= now && tournament_user_signed_up(account) < 0) ||
				tournament_check_client(clienttag) < 0) { /* No Tournament Notice */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0);
				bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0);
			}
			else if (start_prelim >= now) { /* Tournament Notice */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 1);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); /* random */
				bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_prelim));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_prelim - now);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x00);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0);
			}
			else if (end_signup >= now) { /* Tournament Signup Notice - Play Game Active */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 2);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0828); /* random */
				bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(end_signup));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, end_signup - now);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0);
			}
			else if (end_prelim >= now) { /* Tournament Prelim Period - Play Game Active */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 3);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0828); /* random */
				bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(end_prelim));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, end_prelim - now);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0);
			}
			else if (start_r1 >= now && (tournament_get_game_in_progress())) { /* Prelim Period Over - Shows user stats (not all prelim games finished) */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 4);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000); /* random */
				bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_r1));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_r1 - now);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0); /* 00 00 */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x08);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0);
			}
			else if (!(tournament_get_in_finals_status(account))) { /* Prelim Period Over - user did not make finals - Shows user stats */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 5);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0);
				bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, tournament_get_stat(account, 1));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, tournament_get_stat(account, 2));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, tournament_get_stat(account, 3));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0);
			}
			/* cycle through [type-6] & [type-7] packets
			 *
			 * use [type-6] to show client "eliminated" or "continue"
			 *     timestamp , countdown & round number (of next round) must be set if clinet continues
			 *
			 * use [type-7] to make cleint wait for 44FF packet option 1 to start game (A guess, not tested)
			 *
			 * not sure if there is overall winner packet sent at end of last final round
			 */
			// UNDONE: next two conditions never executed
			else if ((0)) { /* User in finals - Shows user stats and start of next round*/
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 6);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0x0000);
				bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, _tournament_time_convert(start_r1));
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0x01);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, start_r1 - now);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0x0000); /* 00 00 */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 4); /* round number */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0); /* 0 = continue , 1= eliminated */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); /* number of rounds in finals */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0);
			}
			else if ((0)) { /* user waiting for match to be made */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.type, 7);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown4, 0);
				bn_int_set(&rpacket->u.server_anongame_tournament_reply.timestamp, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown5, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.countdown, 0);
				bn_short_set(&rpacket->u.server_anongame_tournament_reply.unknown2, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.wins, 1); /* round number */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.losses, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.ties, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.unknown3, 0x04); /* number of finals */
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.selection, 2);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.descnum, 0);
				bn_byte_set(&rpacket->u.server_anongame_tournament_reply.nulltag, 0);
			}

			conn_push_outqueue(c, rpacket);
			packet_del_ref(rpacket);
			return 0;
		}
		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;
		}
		/* Open portrait in Warcraft 3 user profile */
		static int _client_anongame_get_icon(t_connection * c, t_packet const * const packet)
		{
			t_packet * rpacket;
			//BlacKDicK 04/20/2003 Need some huge re-work on this.
			{
				struct
				{
					char	 icon_code[4];
					unsigned int portrait_code;
					char	 race;
					bn_short	 required_wins;
					char	 client_enabled;
				} tempicon;

				//FIXME: Add those to the prefs and also merge them on accoun_wrap;
				// FIXED BY DJP 07/16/2003 FOR 110 CHANGE ( TOURNEY & RACE WINS ) + Table_witdh
				short icon_req_race_wins;
				short icon_req_tourney_wins;
				int race[] = { W3_RACE_RANDOM, W3_RACE_HUMANS, W3_RACE_ORCS, W3_RACE_UNDEAD, W3_RACE_NIGHTELVES, W3_RACE_DEMONS };
				char race_char[6] = { 'R', 'H', 'O', 'U', 'N', 'D' };
				char icon_pos[5] = { '2', '3', '4', '5', '6', };
				char table_width = 6;
				char table_height = 5;
				int i, j;
				char rico;
				unsigned int rlvl, rwins;
				t_clienttag clienttag;
				t_account * acc;

				char user_icon[5];
				char const * uicon;

				clienttag = conn_get_clienttag(c);
				acc = conn_get_account(c);
				/* WAR3 uses a different table size, might change if blizzard add tournament support to RoC */
				if (clienttag == CLIENTTAG_WARCRAFT3_UINT) {
					table_width = 5;
					table_height = 4;
				}

				eventlog(eventlog_level_info, __FUNCTION__, "[%d] got FINDANONGAME Get Icons packet", conn_get_socket(c));

				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_iconreply));
				packet_set_type(rpacket, SERVER_FINDANONGAME_ICONREPLY);
				bn_int_set(&rpacket->u.server_findanongame_iconreply.count, bn_int_get(packet->u.client_findanongame_inforeq.count));
				bn_byte_set(&rpacket->u.server_findanongame_iconreply.option, CLIENT_FINDANONGAME_GET_ICON);
				
				
				if (prefs_get_custom_icons() == 1)
				{
					// get current custom icon
					t_icon_info * icon;
					if (icon = customicons_get_icon_by_account(acc, clienttag))
						std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, icon->icon_code, 4);
				}
				else if ((uicon = account_get_user_icon(acc, clienttag)))
				{
					std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, uicon, 4);
				}
				else
				{
					account_get_raceicon(acc, &rico, &rlvl, &rwins, clienttag);
					std::sprintf(user_icon, "%1d%c3W", rlvl, rico);
					std::memcpy(&rpacket->u.server_findanongame_iconreply.curricon, user_icon, 4);
				}

				bn_byte_set(&rpacket->u.server_findanongame_iconreply.table_width, table_width);
				bn_byte_set(&rpacket->u.server_findanongame_iconreply.table_size, table_width*table_height);
				for (j = 0; j < table_height; j++){
					icon_req_race_wins = anongame_infos_get_ICON_REQ(j + 1, clienttag);
					for (i = 0; i < table_width; i++){
						tempicon.race = i;
						tempicon.icon_code[0] = icon_pos[j];
						tempicon.icon_code[1] = race_char[i];
						tempicon.icon_code[2] = '3';
						tempicon.icon_code[3] = 'W';
						tempicon.portrait_code = (account_icon_to_profile_icon(tempicon.icon_code, acc, clienttag));
						if (i <= 4){
							//Building the icon for the races
							bn_short_set(&tempicon.required_wins, icon_req_race_wins);
							if (account_get_racewins(acc, race[i], clienttag) >= icon_req_race_wins) {
								if (prefs_get_custom_icons() == 1)
									tempicon.client_enabled = 0;
								else
									tempicon.client_enabled = 1;
							}
							else{
								tempicon.client_enabled = 0;
							}
						}
						else{
							//Building the icon for the tourney
							icon_req_tourney_wins = anongame_infos_get_ICON_REQ_TOURNEY(j + 1);
							bn_short_set(&tempicon.required_wins, icon_req_tourney_wins);
							if (account_get_racewins(acc, race[i], clienttag) >= icon_req_tourney_wins) {
								if (prefs_get_custom_icons() == 1)
									tempicon.client_enabled = 0;
								else
									tempicon.client_enabled = 1;
							}
							else{
								tempicon.client_enabled = 0;
							}
						}
						packet_append_data(rpacket, &tempicon, sizeof(tempicon));
					}
				}
				//Go,go,go
				conn_push_outqueue(c, rpacket);
				packet_del_ref(rpacket);
			}
			return 0;
		}
Beispiel #22
0
extern int handle_file_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;
    }
/* REMOVED BY UNDYING SOULZZ 4/3/02 */
/*
    if (packet_get_class(packet)!=packet_class_file)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet));
        return -1;
    }
 */   
    switch (conn_get_state(c))
    {
    case conn_state_connected:
	switch (packet_get_type(packet))
	{
	case CLIENT_FILE_REQ:
	{
	    char const * rawname;
	    
	    if (!(rawname = packet_get_str_const(packet,sizeof(t_client_file_req),MAX_FILENAME_STR)))
	    {
		eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad FILE_REQ (missing or too long filename)",conn_get_socket(c));
		
		return -1;
	    }
	    
	    file_send(c,rawname,
		      bn_int_get(packet->u.client_file_req.adid),
		      bn_int_get(packet->u.client_file_req.extensiontag),
		      bn_int_get(packet->u.client_file_req.startoffset),
		      1);
	}
	break;

	case CLIENT_FILE_REQ2:
	{
	    t_packet * rpacket = NULL;
	    if((rpacket = packet_create(packet_class_raw))) {
		    packet_set_size(rpacket,sizeof(t_server_file_unknown1));
		    bn_int_set( &rpacket->u.server_file_unknown1.unknown, 0xdeadbeef );
		    conn_push_outqueue(c, rpacket );
		    packet_del_ref( rpacket );
	    }
	    conn_set_state(c, conn_state_pending_raw);
	    break;
	}

	default:
	    eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown file packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet));
	    
	    break;
	}
	break;

    case conn_state_pending_raw:
	switch (packet_get_type(packet))
	{
	    case CLIENT_FILE_REQ3:
	    {
		char rawname[MAX_FILENAME_STR];

		psock_recv( conn_get_socket(c), rawname, MAX_FILENAME_STR, 0 );
		file_send(c, rawname, 0, 0, 0, 1);
	    }
	    break;	

	    default:
		eventlog(eventlog_level_error, __FUNCTION__, "[%d] unknown file packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet));

	    break;
	}
	break;

    default:
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown file connection state %d",conn_get_socket(c),(int)conn_get_state(c));
    }

    return 0;
}
Beispiel #23
0
/* Send a file.  If the file doesn't exist we still need to respond
 * to the file request.  This will set filelen to 0 and send the server
 * reply message and the client will be happy and not hang.
 */
extern int file_send(t_connection * c, char const * rawname, unsigned int adid, unsigned int etag, unsigned int startoffset, int need_header)
{
    char const * filename;
    t_packet *   rpacket;
    std::FILE *       fp;
    unsigned int filelen;
    int          nbytes;

    if (!c)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
	return -1;
    }
    if (!rawname)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"got NULL rawname");
	return -1;
    }

    if (!(rpacket = packet_create(packet_class_file)))
    {
	eventlog(eventlog_level_error,__FUNCTION__,"could not create file packet");
	return -1;
    }
    packet_set_size(rpacket,sizeof(t_server_file_reply));
    packet_set_type(rpacket,SERVER_FILE_REPLY);

    if ((filename = file_get_info(rawname,&filelen,&rpacket->u.server_file_reply.timestamp)))
    {
	if (!(fp = std::fopen(filename,"rb")))
	{
	    /* FIXME: check for lower-case version of filename */
	    eventlog(eventlog_level_error,__FUNCTION__, "stat() succeeded yet could not open file \"%s\" for reading (std::fopen: %s)", filename, std::strerror(errno));
	    filelen = 0;
	}
	xfree((void *)filename); /* avoid warning */
    }
    else
    {
	fp = NULL;
	filelen = 0;
	bn_long_set_a_b(&rpacket->u.server_file_reply.timestamp,0,0);
    }

    if (fp)
    {
	if (startoffset<filelen) {
	    std::fseek(fp,startoffset,SEEK_SET);
	} else {
	    eventlog(eventlog_level_warn,__FUNCTION__,"[%d] startoffset is beyond end of file (%u>%u)",conn_get_socket(c),startoffset,filelen);
	    /* Keep the real filesize. Battle.net does it the same way ... */
	    std::fclose(fp);
	    fp = NULL;
	}
    }

    if (need_header)
    {
	/* send the header from the server with the rawname and length. */
	bn_int_set(&rpacket->u.server_file_reply.filelen,filelen);
	bn_int_set(&rpacket->u.server_file_reply.adid,adid);
	bn_int_set(&rpacket->u.server_file_reply.extensiontag,etag);
	/* rpacket->u.server_file_reply.timestamp is set above */
	packet_append_string(rpacket,rawname);
	conn_push_outqueue(c,rpacket);
    }
    packet_del_ref(rpacket);

    /* Now send the data. Since it may be longer than a packet; we use
     * the raw packet class.
     */
    if (!fp)
    {
	eventlog(eventlog_level_warn,__FUNCTION__,"[%d] sending no data for file \"%s\"",conn_get_socket(c),rawname);
	return -1;
    }

    eventlog(eventlog_level_info,__FUNCTION__,"[%d] sending file \"%s\" of length %d",conn_get_socket(c),rawname,filelen);
    for (;;)
    {
	if (!(rpacket = packet_create(packet_class_raw)))
	{
	    eventlog(eventlog_level_error,__FUNCTION__,"could not create raw packet");
	    if (std::fclose(fp)<0)
		eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (std::fclose: %s)",rawname,std::strerror(errno));
	    return -1;
	}
	if ((nbytes = std::fread(packet_get_raw_data_build(rpacket,0),1,MAX_PACKET_SIZE,fp))<(int)MAX_PACKET_SIZE)
	{
	    if (nbytes>0) /* send out last portion */
	    {
		packet_set_size(rpacket,nbytes);
		conn_push_outqueue(c,rpacket);
	    }
	    packet_del_ref(rpacket);
	    if (std::ferror(fp))
		eventlog(eventlog_level_error,__FUNCTION__,"read failed before EOF on file \"%s\" (std::fread: %s)",rawname,std::strerror(errno));
	    break;
	}
	packet_set_size(rpacket,nbytes);
	conn_push_outqueue(c,rpacket);
	packet_del_ref(rpacket);
    }

    if (std::fclose(fp)<0)
	eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (std::fclose: %s)",rawname,std::strerror(errno));
    return 0;
}
Beispiel #24
0
extern int main(int argc, char * argv[])
{
    int                a;
    int                sd;
    struct sockaddr_in saddr;
    t_packet *         packet;
    t_packet *         rpacket;
    t_packet *         fpacket;
    char const *       clienttag=NULL;
    char const *       archtag=NULL;
    char const *       servname=NULL;
    unsigned short     servport=0;
    char const *       hexfile=NULL;
    char               text[MAX_MESSAGE_LEN];
    char const *       reqfile=NULL;
    struct hostent *   host;
    unsigned int       commpos;
    struct termios     in_attr_old;
    struct termios     in_attr_new;
    int                changed_in;
    unsigned int       currsize;
    unsigned int       filelen;
    unsigned int       startoffset;
    int                startoffsetoverride=0;
#define EXIST_ACTION_UNSPEC    -1
#define EXIST_ACTION_ASK        0
#define EXIST_ACTION_OVERWRITE  1
#define EXIST_ACTION_BACKUP     2
#define EXIST_ACTION_RESUME     3 
    int		       exist_action=EXIST_ACTION_UNSPEC;
    struct stat        exist_buf;
    char const *       filename;
    FILE *             fp;
    FILE *             hexstrm=NULL;
    int                fd_stdin;
    t_bnettime         bntime;
    time_t             tm;
    char               timestr[FILE_TIME_MAXLEN];
    unsigned int       screen_width,screen_height;
    int                munged;

    if (argc<1 || !argv || !argv[0])
    {
	fprintf(stderr,"bad arguments\n");
	return STATUS_FAILURE;
    }
    
    for (a=1; a<argc; a++)
	if (servname && isdigit((int)argv[a][0]) && a+1>=argc)
	{
            if (str_to_ushort(argv[a],&servport)<0)
            {
                fprintf(stderr,"%s: \"%s\" should be a positive integer\n",argv[0],argv[a]);
                usage(argv[0]);
            }
	}
	else if (!servname && argv[a][0]!='-' && a+2>=argc)
	    servname = argv[a];
        else if (strcmp(argv[a],"-b")==0 || strcmp(argv[a],"--client=SEXP")==0)
        {
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_BROODWARS;
        }
        else if (strcmp(argv[a],"-d")==0 || strcmp(argv[a],"--client=DRTL")==0)
        {
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_DIABLORTL;
        }
        else if (strcmp(argv[a],"--client=DSHR")==0)
        {
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_DIABLOSHR;
        }
        else if (strcmp(argv[a],"-s")==0 || strcmp(argv[a],"--client=STAR")==0)
        {
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_STARCRAFT;
        }
        else if (strcmp(argv[a],"--client=SSHR")==0)
        {
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_SHAREWARE;
        }
	else if (strcmp(argv[a],"-w")==0 || strcmp(argv[a],"--client=W2BN")==0)
	{
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_WARCIIBNE;
	}
        else if (strcmp(argv[a],"--client=D2DV")==0)
        {
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_DIABLO2DV;
        }
        else if (strcmp(argv[a],"--client=D2XP")==0)
        {
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_DIABLO2XP;
        }
        else if (strcmp(argv[a],"--client=WAR3")==0)
        {
            if (clienttag)
            {
                fprintf(stderr,"%s: client type was already specified as \"%s\"\n",argv[0],clienttag);
                usage(argv[0]);
            }
            clienttag = CLIENTTAG_WARCRAFT3;
        }
        else if (strncmp(argv[a],"--client=",9)==0)
        {
            fprintf(stderr,"%s: unknown client tag \"%s\"\n",argv[0],&argv[a][9]);
            usage(argv[0]);
        }
	else if (strncmp(argv[a],"--hexdump=",10)==0)
	{
	    if (hexfile)
	    {
		fprintf(stderr,"%s: hexdump file was already specified as \"%s\"\n",argv[0],hexfile);
		usage(argv[0]);
	    }
	    hexfile = &argv[a][10];
	}
        else if (strcmp(argv[a],"--arch=IX86")==0)
        {
            if (archtag)
            {
                fprintf(stderr,"%s: client arch was already specified as \"%s\"\n",argv[0],archtag);
                usage(argv[0]);
            }
            archtag = ARCHTAG_WINX86;
        }
        else if (strcmp(argv[a],"--arch=PMAC")==0)
        {
            if (archtag)
            {
                fprintf(stderr,"%s: client arch was already specified as \"%s\"\n",argv[0],archtag);
                usage(argv[0]);
            }
            archtag = ARCHTAG_MACPPC;
        }
        else if (strcmp(argv[a],"--arch=XMAC")==0)
        {
            if (archtag)
            {
                fprintf(stderr,"%s: client arch was already specified as \"%s\"\n",argv[0],archtag);
                usage(argv[0]);
            }
            archtag = ARCHTAG_OSXPPC;
        }
        else if (strncmp(argv[a],"--arch=",7)==0)
        {
            fprintf(stderr,"%s: unknown arch tag \"%s\"\n",argv[0],&argv[a][9]);
            usage(argv[0]);
        }
	else if (strncmp(argv[a],"--startoffset=",14)==0)
	{
	    if (startoffsetoverride)
	    {
		fprintf(stderr,"%s: startoffset was already specified as %u\n",argv[0],startoffset);
		usage(argv[0]);
	    }
            if (str_to_uint(&argv[a][14],&startoffset)<0)
            {
                fprintf(stderr,"%s: startoffset \"%s\" should be a positive integer\n",argv[0],&argv[a][14]);
                usage(argv[0]);
            }
	    startoffsetoverride = 1;
	}
	else if (strncmp(argv[a],"--exists=",9)==0)
	{
	    if (exist_action!=EXIST_ACTION_UNSPEC)
	    {
		fprintf(stderr,"%s: exists was already specified\n",argv[0]);
		usage(argv[0]);
	    }
	    if (argv[a][9]=='o' || argv[a][9]=='O')
	    	exist_action = EXIST_ACTION_OVERWRITE;
	    else if (argv[a][9]=='a' || argv[a][9]=='A')
	    	exist_action = EXIST_ACTION_ASK;
	    else if (argv[a][9]=='b' || argv[a][9]=='B')
	    	exist_action = EXIST_ACTION_BACKUP;
	    else if (argv[a][9]=='r' || argv[a][9]=='R')
	    	exist_action = EXIST_ACTION_RESUME;
	    else {
		fprintf(stderr,"%s: exists must begin with a,A,o,O,b,B,r or R",argv[0]);
		usage(argv[0]);
	    }
	}
	else if (strncmp(argv[a],"--file=",7)==0)
	{
	    if (reqfile)
	    {
		fprintf(stderr,"%s: file was already specified as \"%s\"\n",argv[0],reqfile);
		usage(argv[0]);
	    }
	    reqfile = &argv[a][7];
	}
	else if (strcmp(argv[a],"-v")==0 || strcmp(argv[a],"--version")==0)
	{
            printf("version "BNETD_VERSION"\n");
            return 0;
	}
	else if (strcmp(argv[a],"-h")==0 || strcmp(argv[a],"--help")==0 || strcmp(argv[a],"--usage")==0)
            usage(argv[0]);
        else if (strcmp(argv[a],"--client")==0 || strcmp(argv[a],"--hexdump")==0)
        {
            fprintf(stderr,"%s: option \"%s\" requires an argument\n",argv[0],argv[a]);
            usage(argv[0]);
        }
	else
	{
	    fprintf(stderr,"%s: unknown option \"%s\"\n",argv[0],argv[a]);
	    usage(argv[0]);
	}
    
    if (servport==0)
        servport = BNETD_SERV_PORT;
    if (!clienttag)
        clienttag = CLIENTTAG_STARCRAFT;
    if (!archtag)
        archtag = ARCHTAG_WINX86;
    if (!servname)
	servname = BNETD_DEFAULT_HOST;
    if (exist_action==EXIST_ACTION_UNSPEC)
	exist_action = EXIST_ACTION_ASK;
    
    if (hexfile)
	if (!(hexstrm = fopen(hexfile,"w")))
	    fprintf(stderr,"%s: could not open file \"%s\" for writing the hexdump (fopen: %s)",argv[0],hexfile,strerror(errno));
	else
	    fprintf(hexstrm,"# dump generated by bnftp version "BNETD_VERSION"\n");
    
    if (psock_init()<0)
    {
        fprintf(stderr,"%s: could not inialialize socket functions\n",argv[0]);
        return STATUS_FAILURE;
    }
    
    if (!(host = gethostbyname(servname)))
    {
	fprintf(stderr,"%s: unknown host \"%s\"\n",argv[0],servname);
	return STATUS_FAILURE;
    }
    
    fd_stdin = fileno(stdin);
    if (tcgetattr(fd_stdin,&in_attr_old)>=0)
    {
        in_attr_new = in_attr_old;
        in_attr_new.c_lflag &= ~(ECHO | ICANON); /* turn off ECHO and ICANON */
	in_attr_new.c_cc[VMIN]  = 1; /* require reads to return at least one byte */
        in_attr_new.c_cc[VTIME] = 0; /* no timeout */
        tcsetattr(fd_stdin,TCSANOW,&in_attr_new);
        changed_in = 1;
    }
    else
    {
	fprintf(stderr,"%s: could not get terminal attributes for stdin\n",argv[0]);
	changed_in = 0;
    }
    
    if (client_get_termsize(fd_stdin,&screen_width,&screen_height)<0)
    {
        fprintf(stderr,"%s: could not determine screen size\n",argv[0]);
        if (changed_in)
            tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
        return STATUS_FAILURE;
    }
    
    if ((sd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0)
    {
	fprintf(stderr,"%s: could not create socket (psock_socket: %s)\n",argv[0],strerror(psock_errno()));
	if (changed_in)
	    tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
	return STATUS_FAILURE;
    }
    
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = PSOCK_AF_INET;
    saddr.sin_port   = htons(servport);
    memcpy(&saddr.sin_addr.s_addr,host->h_addr_list[0],host->h_length);
    if (psock_connect(sd,(struct sockaddr *)&saddr,sizeof(saddr))<0)
    {
	fprintf(stderr,"%s: could not connect to server \"%s\" port %hu (psock_connect: %s)\n",argv[0],servname,servport,strerror(psock_errno()));
	if (changed_in)
	    tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
	return STATUS_FAILURE;
    }
    
    printf("Connected to %s:%hu.\n",inet_ntoa(saddr.sin_addr),servport);
    
#ifdef CLIENTDEBUG
    eventlog_set(stderr);
#endif
    
    if (!(packet = packet_create(packet_class_init)))
    {
	fprintf(stderr,"%s: could not create packet\n",argv[0]);
	if (changed_in)
	    tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
	return STATUS_FAILURE;
    }
    bn_byte_set(&packet->u.client_initconn.class,CLIENT_INITCONN_CLASS_FILE);
    if (hexstrm)
    {
	fprintf(hexstrm,"%d: send class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n",
		sd,
		packet_get_class_str(packet),(unsigned int)packet_get_class(packet),
		packet_get_type_str(packet,packet_dir_from_client),packet_get_type(packet),
		packet_get_size(packet));
	hexdump(hexstrm,packet_get_raw_data(packet,0),packet_get_size(packet));
    }
    client_blocksend_packet(sd,packet);
    packet_del_ref(packet);
    
    if (!(rpacket = packet_create(packet_class_file)))
    {
	fprintf(stderr,"%s: could not create packet\n",argv[0]);
	if (changed_in)
	    tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
	return STATUS_FAILURE;
    }
    
    if (!(fpacket = packet_create(packet_class_raw)))
    {
	fprintf(stderr,"%s: could not create packet\n",argv[0]);
	if (changed_in)
	    tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
	packet_del_ref(rpacket);
	return STATUS_FAILURE;
    }
    
    if (!reqfile) /* if not specified on the command line then prompt for it */
    {
    	munged = 1;
    	commpos = 0;
    	text[0] = '\0';
	
    	for (;;)
    	{
	    switch (client_get_comm("filename: ",text,sizeof(text),&commpos,1,munged,screen_width))
	    {
	    case -1: /* cancel or error */
	    	printf("\n");
	    	if (changed_in)
		    tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
	    	packet_del_ref(fpacket);
	    	packet_del_ref(rpacket);
	    	return STATUS_FAILURE;
		
	    case 0: /* timeout */
	    	munged = 0;
	    	continue;
		
	    case 1:
	    	munged = 0;
	    	if (text[0]=='\0')
		    continue;
	    	printf("\n");
	    }
	    break;
    	}
	reqfile = text;
    }
    
    if (stat(reqfile,&exist_buf)==0) /* check if the file exists */
    {
	char text2[MAX_MESSAGE_LEN];
	    
    	munged = 1;
	commpos = 0;
	text2[0] = '\0';
	
  	while (exist_action==EXIST_ACTION_ASK)
	{
	    switch (client_get_comm("File exists [O]verwrite, [B]ackup or [R]esume?: ",text2,sizeof(text2),&commpos,1,munged,screen_width))
	    {
	    case -1: /* cancel or error */
	    	printf("\n");
	    	if (changed_in)
		    tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
	    	packet_del_ref(fpacket);
	    	packet_del_ref(rpacket);
	    	return STATUS_FAILURE;
		
	    case 0: /* timeout */
	    	munged = 0;
	    	continue;
		
	    case 1:
	    	munged = 0;
	    	if (text2[0]=='\0')
		    continue;
	    	printf("\n");
		break;
	    }
	    
	    switch (text2[0])
	    {
	    case 'o':
	    case 'O':
		exist_action = EXIST_ACTION_OVERWRITE;
		break;
	    case 'b':
	    case 'B':
		exist_action = EXIST_ACTION_BACKUP;
		break;
	    case 'r':
	    case 'R':
		exist_action = EXIST_ACTION_RESUME;
		break;
	    default:
		printf("Please answer with o,O,b,B,r or R.\n");
		munged = 1;
		continue;
	    }
	    break;
	}
	
	switch (exist_action)
	{
	case EXIST_ACTION_OVERWRITE:
	    if (!startoffsetoverride)
	    	startoffset = 0;
	    break;
	case EXIST_ACTION_BACKUP:
	    {
		char *       bakfile;
		unsigned int bnr;
		int          renamed=0;
		
		if (!(bakfile = malloc(strlen(reqfile)+1+2+1))) /* assuming we go up to bnr 99 we need reqfile+'.'+'99'+'\0' */
		{
		    fprintf(stderr,"%s: unable to allocate memory for backup filename.\n",argv[0]);
		    if (changed_in)
			tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
		    packet_del_ref(fpacket);
		    packet_del_ref(rpacket);
		    return STATUS_FAILURE;
		}
		
		for (bnr=0; bnr<100; bnr++)
		{
		    sprintf(bakfile,"%s.%d",reqfile,bnr);
		    if (stat(bakfile,&exist_buf)==0)
			continue; /* backup exists */
		    /* backup does not exist */
		    if (rename(reqfile,bakfile)<0) /* just rename the existing file to the backup */
			fprintf(stderr,"%s: could not create backup file \"%s\" (rename: %s)\n",argv[0],bakfile,strerror(errno));
		    else
		    {
			renamed = 1;
			printf("Renaming \"%s\" to \"%s\".\n",reqfile,bakfile);
		    }
		    break;
		}
		free(bakfile);
		if (!renamed)
		{
		    fprintf(stderr,"%s: could not create backup for \"%s\".\n",argv[0],reqfile);
		    if (changed_in)
			tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
		    packet_del_ref(fpacket);
		    packet_del_ref(rpacket);
		    return STATUS_FAILURE;
		}
	    	if (!startoffsetoverride)
	    	    startoffset = 0;
	    }
	    break;
	case EXIST_ACTION_RESUME:
	    if (!startoffsetoverride)
	    	startoffset = exist_buf.st_size;
	    break;	    	
	}	
    }
    else
	if (!startoffsetoverride)
	    startoffset = 0;
    
    if (changed_in)
	tcsetattr(fd_stdin,TCSAFLUSH,&in_attr_old);
    
    if (!(packet = packet_create(packet_class_file)))
    {
	fprintf(stderr,"%s: could not create packet\n",argv[0]);
	packet_del_ref(fpacket);
	packet_del_ref(rpacket);
	return STATUS_FAILURE;
    }
    packet_set_size(packet,sizeof(t_client_file_req));
    packet_set_type(packet,CLIENT_FILE_REQ);
    bn_int_tag_set(&packet->u.client_file_req.archtag,archtag);
    bn_int_tag_set(&packet->u.client_file_req.clienttag,clienttag);
    bn_int_set(&packet->u.client_file_req.adid,0);
    bn_int_set(&packet->u.client_file_req.extensiontag,0);
    bn_int_set(&packet->u.client_file_req.startoffset,startoffset);
    bn_long_set_a_b(&packet->u.client_file_req.timestamp,0x00000000,0x00000000);
    packet_append_string(packet,reqfile);
    if (hexstrm)
    {
	fprintf(hexstrm,"%d: send class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n",
		sd,
		packet_get_class_str(packet),(unsigned int)packet_get_class(packet),
		packet_get_type_str(packet,packet_dir_from_client),packet_get_type(packet),
		packet_get_size(packet));
	hexdump(hexstrm,packet_get_raw_data(packet,0),packet_get_size(packet));
    }
    printf("\nRequesting info...");
    fflush(stdout);
    client_blocksend_packet(sd,packet);
    packet_del_ref(packet);
    
    do
    {
	if (client_blockrecv_packet(sd,rpacket)<0)
	{
	    fprintf(stderr,"%s: server closed connection\n",argv[0]);
	    packet_del_ref(fpacket);
	    packet_del_ref(rpacket);
	    return STATUS_FAILURE;
	}
	if (hexstrm)
	{
	    fprintf(hexstrm,"%d: recv class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n",
		     sd,
		     packet_get_class_str(rpacket),(unsigned int)packet_get_class(rpacket),
		     packet_get_type_str(rpacket,packet_dir_from_server),packet_get_type(rpacket),
		     packet_get_size(rpacket));
	    hexdump(hexstrm,packet_get_raw_data(rpacket,0),packet_get_size(rpacket));
	}
    }
    while (packet_get_type(rpacket)!=SERVER_FILE_REPLY);
    
    filelen = bn_int_get(rpacket->u.server_file_reply.filelen);
    bn_long_to_bnettime(rpacket->u.server_file_reply.timestamp,&bntime);
    tm = bnettime_to_time(bntime);
    strftime(timestr,FILE_TIME_MAXLEN,FILE_TIME_FORMAT,localtime(&tm));
    filename = packet_get_str_const(rpacket,sizeof(t_server_file_reply),MAX_FILENAME_STR);
    
    if (exist_action==EXIST_ACTION_RESUME)
    {
	if (!(fp = fopen(reqfile,"ab")))
	{
	    fprintf(stderr,"%s: could not open file \"%s\" for appending (fopen: %s)\n",argv[0],reqfile,strerror(errno));
	    packet_del_ref(fpacket);
	    packet_del_ref(rpacket);
	    return STATUS_FAILURE;
	}
    }
    else
    {
	if (!(fp = fopen(reqfile,"wb")))
	{
	    fprintf(stderr,"%s: could not open file \"%s\" for writing (fopen: %s)\n",argv[0],reqfile,strerror(errno));
	    packet_del_ref(fpacket);
	    packet_del_ref(rpacket);
	    return STATUS_FAILURE;
	}
    }
    
    printf("\n name: \"");
    str_print_term(stdout,filename,0,0);
    printf("\"\n changed: %s\n length: %u bytes\n",timestr,filelen);
    fflush(stdout);
    
    if (startoffset>0) {
	filelen -= startoffset; /* for resuming files */
	printf("Resuming at position %u (%u bytes remaining).\n",startoffset,filelen);
    }
    
    printf("\nSaving to \"%s\"...",reqfile);

    for (currsize=0; currsize+MAX_PACKET_SIZE<=filelen; currsize+=MAX_PACKET_SIZE)
    {
	printf(".");
	fflush(stdout);
	
	if (client_blockrecv_raw_packet(sd,fpacket,MAX_PACKET_SIZE)<0)
	{
	    printf("error\n");
	    fprintf(stderr,"%s: server closed connection\n",argv[0]);
	    if (fclose(fp)<0)
		fprintf(stderr,"%s: could not close file \"%s\" after writing (fclose: %s)\n",argv[0],reqfile,strerror(errno));
	    packet_del_ref(fpacket);
	    packet_del_ref(rpacket);
	    return STATUS_FAILURE;
	}
	if (hexstrm)
	{
	    fprintf(hexstrm,"%d: recv class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n",
		     sd,
		     packet_get_class_str(fpacket),(unsigned int)packet_get_class(fpacket),
		     packet_get_type_str(fpacket,packet_dir_from_server),packet_get_type(fpacket),
		     packet_get_size(fpacket));
	    hexdump(hexstrm,packet_get_raw_data(fpacket,0),packet_get_size(fpacket));
	}
	if (fwrite(packet_get_raw_data_const(fpacket,0),1,MAX_PACKET_SIZE,fp)<MAX_PACKET_SIZE)
	{
	    printf("error\n");
	    fprintf(stderr,"%s: could not write to file \"%s\" (fwrite: %s)\n",argv[0],reqfile,strerror(errno));
	    if (fclose(fp)<0)
		fprintf(stderr,"%s: could not close file \"%s\" after writing (fclose: %s)\n",argv[0],reqfile,strerror(errno));
	    packet_del_ref(fpacket);
	    packet_del_ref(rpacket);
	    return STATUS_FAILURE;
	}
    }
    filelen -= currsize;
    if (filelen)
    {
	printf(".");
	fflush(stdout);
	
	if (client_blockrecv_raw_packet(sd,fpacket,filelen)<0)
	{
	    printf("error\n");
	    fprintf(stderr,"%s: server closed connection\n",argv[0]);
	    if (fclose(fp)<0)
		fprintf(stderr,"%s: could not close file \"%s\" after writing (fclose: %s)\n",argv[0],reqfile,strerror(errno));
	    packet_del_ref(fpacket);
	    packet_del_ref(rpacket);
	    return STATUS_FAILURE;
	}
	if (hexstrm)
	{
	    fprintf(hexstrm,"%d: recv class=%s[0x%02hx] type=%s[0x%04hx] length=%u\n",
		     sd,
		     packet_get_class_str(fpacket),(unsigned int)packet_get_class(fpacket),
		     packet_get_type_str(fpacket,packet_dir_from_server),packet_get_type(fpacket),
		     packet_get_size(fpacket));
	    hexdump(hexstrm,packet_get_raw_data(fpacket,0),packet_get_size(fpacket));
	}
	if (fwrite(packet_get_raw_data_const(fpacket,0),1,filelen,fp)<filelen)
	{
	    printf("error\n");
	    fprintf(stderr,"%s: could not write to file \"%s\"\n",argv[0],reqfile);
	    if (fclose(fp)<0)
		fprintf(stderr,"%s: could not close file \"%s\" after writing (fclose: %s)\n",argv[0],reqfile,strerror(errno));
	    packet_del_ref(fpacket);
	    packet_del_ref(rpacket);
	    return STATUS_FAILURE;
	}
    }
    
    packet_del_ref(fpacket);
    packet_del_ref(rpacket);
    
    if (hexstrm)
    {
	fprintf(hexstrm,"# end of dump\n");
	if (fclose(hexstrm)<0)
	    fprintf(stderr,"%s: could not close hexdump file \"%s\" after writing (fclose: %s)",argv[0],hexfile,strerror(errno));
    }
    
    if (fclose(fp)<0)
    {
	fprintf(stderr,"%s: could not close file \"%s\" after writing (fclose: %s)\n",argv[0],reqfile,strerror(errno));
	return STATUS_FAILURE;
    }
    
    printf("done\n");
    return STATUS_FAILURE;
}
Beispiel #25
0
static int on_d2cs_charloginreq(t_connection * c, t_packet const * packet)
{
	t_connection * client;
	char const * charname;
	char const * portrait;
	char const * clienttag;
	char		* temp;
	unsigned int	sessionnum;
	char const * tname;
	char const * realmname;
	unsigned int	pos, reply;
	t_packet	* rpacket;
	
	if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_charloginreq)) {
		eventlog(eventlog_level_error,"on_d2cs_charloginreq","got bad packet size");
		return -1;
	}
	sessionnum=bn_int_get(packet->u.d2cs_bnetd_charloginreq.sessionnum);
	pos=sizeof(t_d2cs_bnetd_charloginreq);
	if (!(charname=packet_get_str_const(packet,pos,CHAR_NAME_LEN))) {
		eventlog(eventlog_level_error,"on_d2cs_charloginreq","got bad character name");
		return -1;
	}
	pos+=strlen(charname)+1;
	if (!(portrait=packet_get_str_const(packet,pos,CHAR_PORTRAIT_LEN))) {
		eventlog(eventlog_level_error,"on_d2cs_charloginreq","got bad character portrait");
		return -1;
	}
	if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) {
		eventlog(eventlog_level_error,"on_d2cs_charloginreq","user %d not found",sessionnum);
		reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
	} else if (!(clienttag=conn_get_clienttag(client))) {
		eventlog(eventlog_level_error,"on_d2cs_charloginreq","got NULL clienttag");
		reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
	} else if (!(realmname=conn_get_realmname(client))) {
		eventlog(eventlog_level_error,"on_d2cs_charloginreq","got NULL realm name");
		reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
	} else if (!(temp=malloc(strlen(clienttag)+strlen(realmname)+1+strlen(charname)+1+\
			strlen(portrait)+1))) {
		eventlog(eventlog_level_error,"on_d2cs_charloginreq","error allocate temp");
		reply = BNETD_D2CS_CHARLOGINREPLY_FAILED;
	} else {
		reply = BNETD_D2CS_CHARLOGINREPLY_SUCCEED;
		sprintf (temp,"PX2D%s,%s,%s",realmname,charname,portrait);
		bn_int_tag_set((bn_int *)temp,clienttag);
		conn_set_charname(client,charname);
		conn_set_realminfo(client,temp);
		free(temp);
		eventlog(eventlog_level_debug,"on_d2cs_charloginreq",\
			"loaded portrait for character %s",charname);
	}
	if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
		packet_set_size(rpacket,sizeof(t_bnetd_d2cs_charloginreply));
		packet_set_type(rpacket,BNETD_D2CS_CHARLOGINREPLY);
		bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.h.seqno,\
			bn_int_get(packet->u.d2cs_bnetd_charloginreq.h.seqno));
		bn_int_set(&rpacket->u.bnetd_d2cs_charloginreply.reply,reply);
		queue_push_packet(conn_get_out_queue(c),rpacket);
		packet_del_ref(rpacket);
	}
	return 0;
}
Beispiel #26
0
static int on_d2cs_accountloginreq(t_connection * c, t_packet const * packet)
{
	unsigned int	sessionkey;
	unsigned int	sessionnum;
	unsigned int	salt;
	char const *	account;
	char const *	tname;
	t_connection	* client;
	int		reply;
	t_packet	* rpacket;
	struct
	{
		bn_int   salt;
		bn_int   sessionkey;
		bn_int   sessionnum;
		bn_int   secret;
		bn_int	 passhash[5];
	} temp;
	t_hash       secret_hash;
	char const * pass_str;
	t_hash	     passhash;
	t_hash	     try_hash;

	if (packet_get_size(packet)<sizeof(t_d2cs_bnetd_accountloginreq)) {
		eventlog(eventlog_level_error,"on_d2cs_accountloginreq","got bad packet size");
		return -1;
	}
	if (!(account=packet_get_str_const(packet,sizeof(t_d2cs_bnetd_accountloginreq),USER_NAME_MAX))) {
		eventlog(eventlog_level_error,"on_d2cs_accountloginreq","got bad account name");
		return -1;
	}
	sessionkey=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionkey);
	sessionnum=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.sessionnum);
	salt=bn_int_get(packet->u.d2cs_bnetd_accountloginreq.seqno);
	if (!(client=connlist_find_connection_by_sessionnum(sessionnum))) {
		eventlog(eventlog_level_error,"on_d2cs_accountloginreq","sessionnum %d not found",sessionnum);
		reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
	} else if (sessionkey!=conn_get_sessionkey(client)) {
		eventlog(eventlog_level_error,"on_d2cs_accountloginreq","sessionkey %d not match",sessionkey);
		reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
	} else if (!(tname=conn_get_username(client))) {
		eventlog(eventlog_level_error,"on_d2cs_accountloginreq","got NULL username");
		reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
	} else if (strcasecmp(account,tname)) {
		eventlog(eventlog_level_error,"on_d2cs_accountloginreq","username %s not match",account);
		conn_unget_username(client,tname);
		reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
	} else {
		conn_unget_username(client,tname);
		bn_int_set(&temp.salt,salt);
		bn_int_set(&temp.sessionkey,sessionkey);
		bn_int_set(&temp.sessionnum,sessionnum);
		bn_int_set(&temp.secret,conn_get_secret(client));
		pass_str=account_get_pass(conn_get_account(client));
		if (hash_set_str(&passhash,pass_str)<0) {
			reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
		} else {
			hash_to_bnhash((t_hash const *)&passhash,temp.passhash);
			bnet_hash(&secret_hash,sizeof(temp),&temp);
			bnhash_to_hash(packet->u.d2cs_bnetd_accountloginreq.secret_hash,&try_hash);
			if (hash_eq(try_hash,secret_hash)==1) {
				eventlog(eventlog_level_debug,"on_d2cs_accountloginreq","user %s loggedin on d2cs",\
					account);
				reply=BNETD_D2CS_ACCOUNTLOGINREPLY_SUCCEED;
			} else {
				eventlog(eventlog_level_error,"on_d2cs_accountloginreq","user %s hash not match",\
					account);
				reply=BNETD_D2CS_ACCOUNTLOGINREPLY_FAILED;
			}
		}
		account_unget_pass(pass_str);
	}
	if ((rpacket=packet_create(packet_class_d2cs_bnetd))) {
		packet_set_size(rpacket,sizeof(t_bnetd_d2cs_accountloginreply));
		packet_set_type(rpacket,BNETD_D2CS_ACCOUNTLOGINREPLY);
		bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.h.seqno,\
			bn_int_get(packet->u.d2cs_bnetd_accountloginreq.h.seqno));
		bn_int_set(&rpacket->u.bnetd_d2cs_accountloginreply.reply,reply);
		queue_push_packet(conn_get_out_queue(c),rpacket);
		packet_del_ref(rpacket);
	}
	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;
}
Beispiel #28
0
static int on_bnetd_charloginreply(t_connection * c, t_packet * packet)
{
	unsigned int	seqno;
	t_sq		* sq;
	t_connection	* client;
	t_packet	* opacket, * rpacket;
	int		result, reply, type;
	char const	* charname;
	t_elem		* elem;

	if (!packet || !c)
	    return -1;

	seqno=bn_int_get(packet->u.d2cs_bnetd.h.seqno);
	if (!(sq=sqlist_find_sq(seqno))) {
		eventlog(eventlog_level_error,__FUNCTION__,"seqno %d not found",seqno);
		return -1;
	}
	if (!(client=d2cs_connlist_find_connection_by_sessionnum(sq_get_clientid(sq)))) {
		eventlog(eventlog_level_error,__FUNCTION__,"client %d not found",sq_get_clientid(sq));
		sq_destroy(sq,&elem);
		return -1;
	}
	if (!(opacket=sq_get_packet(sq))) {
		eventlog(eventlog_level_error,__FUNCTION__,"previous packet missing (seqno: %d)",seqno);
		sq_destroy(sq,&elem);
		return -1;
	}
	type=packet_get_type(opacket);
	result=bn_int_get(packet->u.bnetd_d2cs_charloginreply.reply);
	if (type==CLIENT_D2CS_CREATECHARREQ) {
		charname=packet_get_str_const(opacket,sizeof(t_client_d2cs_createcharreq),MAX_CHARNAME_LEN);
		if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) {
			if (conn_check_multilogin(client,charname)<0) {
				eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname);
				reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED;
			} else {
				reply= D2CS_CLIENT_CREATECHARREPLY_SUCCEED;
				eventlog(eventlog_level_info,__FUNCTION__,"character %s authed",charname);
				d2cs_conn_set_charname(client,charname);
				d2cs_conn_set_state(client,conn_state_char_authed);
			}
		} else {
			reply = D2CS_CLIENT_CREATECHARREPLY_FAILED;
			eventlog(eventlog_level_error,__FUNCTION__,"failed to auth character %s",charname);
		}
		if ((rpacket=packet_create(packet_class_d2cs))) {
			packet_set_size(rpacket,sizeof(t_d2cs_client_createcharreply));
			packet_set_type(rpacket,D2CS_CLIENT_CREATECHARREPLY);
			bn_int_set(&rpacket->u.d2cs_client_createcharreply.reply,reply);
			conn_push_outqueue(client,rpacket);
			packet_del_ref(rpacket);
		}
	} else if (type==CLIENT_D2CS_CHARLOGINREQ) {
		charname=packet_get_str_const(opacket,sizeof(t_client_d2cs_charloginreq),MAX_CHARNAME_LEN);
		if (result==BNETD_D2CS_CHARLOGINREPLY_SUCCEED) {
			if (conn_check_multilogin(client,charname)<0) {
				eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname);
				reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED;
			} else {
				reply = D2CS_CLIENT_CHARLOGINREPLY_SUCCEED;
				eventlog(eventlog_level_info,__FUNCTION__,"character %s authed",charname);
				d2cs_conn_set_charname(client,charname);
				d2cs_conn_set_state(client,conn_state_char_authed);
			}
		} else {
			reply = D2CS_CLIENT_CHARLOGINREPLY_FAILED;
			eventlog(eventlog_level_error,__FUNCTION__,"failed to auth character %s",charname);
		}
		if ((rpacket=packet_create(packet_class_d2cs))) {
			packet_set_size(rpacket,sizeof(t_d2cs_client_charloginreply));
			packet_set_type(rpacket,D2CS_CLIENT_CHARLOGINREPLY);
			bn_int_set(&rpacket->u.d2cs_client_charloginreply.reply,reply);
			conn_push_outqueue(client,rpacket);
			packet_del_ref(rpacket);
		}
	} else {
		eventlog(eventlog_level_error,__FUNCTION__,"got bad packet type %d",type);
		sq_destroy(sq,&elem);
		return -1;
	}
	sq_destroy(sq,&elem);
	return 0;
}
static int on_client_joingamereq(t_connection * c, t_packet * packet)
{
	char const	* gamename;
	char const	* gamepass;
	char const	* charname;
	char const	* account;
	t_game		* game;
	t_d2gs		* gs;
	int		reply;
	unsigned int	pos;
	unsigned int	seqno;

	gs = NULL;
	pos=sizeof(t_client_d2cs_joingamereq);
	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;
	}
	if (!(charname=d2cs_conn_get_charname(c))) {
		eventlog(eventlog_level_error,__FUNCTION__,"missing character name for connection");
		return -1;
	}
	if (!(account=d2cs_conn_get_account(c))) {
		eventlog(eventlog_level_error,__FUNCTION__,"missing account for connection");
		return -1;
	}
	if (conn_check_multilogin(c,charname)<0) {
		eventlog(eventlog_level_error,__FUNCTION__,"character %s is already logged in",charname);
		return -1;
	}
	if (!(game=d2cs_gamelist_find_game(gamename))) {
		eventlog(eventlog_level_info,__FUNCTION__,"game %s not found",gamename);
		reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST;
	} else if (!(gs=game_get_d2gs(game))) {
		eventlog(eventlog_level_error,__FUNCTION__,"missing game server for game %s",gamename);
		reply=D2CS_CLIENT_JOINGAMEREPLY_NOT_EXIST;
	} else {
		reply=d2cs_try_joingame(c,game,gamepass);
	}

	seqno=bn_short_get(packet->u.client_d2cs_joingamereq.seqno);
	if (reply!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) {
		t_packet	* rpacket;

		if ((rpacket=packet_create(packet_class_d2cs))) {
			packet_set_size(rpacket,sizeof(t_d2cs_client_joingamereply));
			packet_set_type(rpacket,D2CS_CLIENT_JOINGAMEREPLY);
			bn_short_set(&rpacket->u.d2cs_client_joingamereply.seqno,seqno);
			bn_short_set(&rpacket->u.d2cs_client_joingamereply.u1,0);
			bn_short_set(&rpacket->u.d2cs_client_joingamereply.gameid,0);
			bn_int_set(&rpacket->u.d2cs_client_joingamereply.addr,0);
			bn_int_set(&rpacket->u.d2cs_client_joingamereply.token,0);
			bn_int_set(&rpacket->u.d2cs_client_joingamereply.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_joingamereq));
				packet_set_type(gspacket,D2CS_D2GS_JOINGAMEREQ);
				bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.h.seqno,sq_get_seqno(sq));
				bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.gameid,
					game_get_d2gs_gameid(game));
				sq_set_gametoken(sq,d2gs_make_token(gs));
				bn_int_set(&gspacket->u.d2cs_d2gs_joingamereq.token,sq_get_gametoken(sq));
				packet_append_string(gspacket,charname);
				packet_append_string(gspacket,account);
				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 join game %s for character %s on gs %d",gamename,
				charname,d2gs_get_id(gs));
		}
	}
	return 0;
}
static int on_client_gamelistreq(t_connection * c, t_packet * packet)
{
	t_packet	* rpacket;
	t_game		* game;
	unsigned int	count;
	unsigned int	seqno;
	std::time_t		now;
	unsigned int	maxlifetime;
	t_elem const	* start_elem;
	t_elem const	* elem;

	seqno=bn_short_get(packet->u.client_d2cs_gamelistreq.seqno);
	/* if (seqno%2) return 0; */
	count=0;
	now=std::time(NULL);
	maxlifetime=prefs_get_game_maxlifetime();

	elem=start_elem=gamelist_get_curr_elem();
	if (!elem) elem=list_get_first_const(d2cs_gamelist());
	else elem=elem_get_next_const(d2cs_gamelist(),elem);

	for (; elem != start_elem; elem=elem_get_next_const(d2cs_gamelist(),elem)) {
		if (!elem) {
			elem=list_get_first_const(d2cs_gamelist());
			if (elem == start_elem) break;
		}
		if (!(game=(t_game*)elem_get_data(elem))) {
			eventlog(eventlog_level_error,__FUNCTION__,"got NULL game");
			break;
		}
		if (maxlifetime && (now-game->create_time>maxlifetime)) continue;
		if (!game_get_currchar(game)) continue;
		if (!prefs_allow_gamelist_showall()) {
			if (conn_get_charinfo_difficulty(c)!=game_get_gameflag_difficulty(game)) continue;
		}
		if (prefs_hide_pass_games())
			if (d2cs_game_get_pass(game)) continue;

		if (d2cs_try_joingame(c,game,"")!=D2CS_CLIENT_JOINGAMEREPLY_SUCCEED) continue;
		if ((rpacket=packet_create(packet_class_d2cs))) {
			packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply));
			packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY);
			bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno);
			bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,d2cs_game_get_id(game));
			bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,game_get_currchar(game));
			bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,game_get_gameflag(game));
			packet_append_string(rpacket,d2cs_game_get_name(game));
			packet_append_string(rpacket,game_get_desc(game));
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
			count++;
			if (prefs_get_maxgamelist() && count>=prefs_get_maxgamelist()) break;
		}
	}
	gamelist_set_curr_elem(elem);
	if (count) {
		if ((rpacket=packet_create(packet_class_d2cs))) {
			packet_set_size(rpacket,sizeof(t_d2cs_client_gamelistreply));
			packet_set_type(rpacket,D2CS_CLIENT_GAMELISTREPLY);
			bn_short_set(&rpacket->u.d2cs_client_gamelistreply.seqno,seqno);
			bn_int_set(&rpacket->u.d2cs_client_gamelistreply.token,0);
			bn_byte_set(&rpacket->u.d2cs_client_gamelistreply.currchar,0);
			bn_int_set(&rpacket->u.d2cs_client_gamelistreply.gameflag,0);
			packet_append_string(rpacket,"");
			packet_append_string(rpacket,"");
			packet_append_string(rpacket,"");
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
		}
	}
	return 0;
}