예제 #1
0
static int on_d2cs_initconn(t_connection * c)
{
	eventlog(eventlog_level_info, __FUNCTION__, "[%d] client initiated d2cs connection",conn_get_socket(c));
	conn_set_class(c,conn_class_d2cs);
	conn_set_state(c,conn_state_connected);
	return 0;
}
예제 #2
0
파일: irc.c 프로젝트: 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;
}
예제 #3
0
extern int realm_active(t_realm * realm, t_connection * c)
{
    if (!realm)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"got NULL realm");
        return -1;
    }
    if (!c)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"got NULL connection");
        return -1;
    }
    if (realm->active)
    {
        eventlog(eventlog_level_debug,__FUNCTION__, "realm %s is already actived,destroy previous one",realm->name);
        realm_deactive(realm);
    }
    realm->active=1;
    realm->conn=c;
    conn_set_realm(c,realm);
    realm->sessionnum=conn_get_sessionnum(c);
    realm->tcp_sock=conn_get_socket(c);
    eventlog(eventlog_level_info,__FUNCTION__, "realm %s actived",realm->name);
    return 0;
}
예제 #4
0
파일: irc.c 프로젝트: 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;
}
예제 #5
0
static int on_d2gs_initconn(t_connection * c)
{
	t_d2gs * gs;

	eventlog(eventlog_level_info, __FUNCTION__, "[%d] client initiated d2gs connection",conn_get_socket(c));
	if (!(gs=d2gslist_find_gs_by_ip(conn_get_addr(c)))) {
		/* reload list and see if any dns addy's has changed */
		if (d2gslist_reload(prefs_get_d2gs_list())<0) {
			eventlog(eventlog_level_error, __FUNCTION__, "error reloading game server list,exitting");
			return -1;
		}
		/* recheck */
		if (!(gs=d2gslist_find_gs_by_ip(conn_get_addr(c)))) {
			eventlog(eventlog_level_error, __FUNCTION__, "d2gs connection from invalid ip address %s",addr_num_to_ip_str(conn_get_addr(c)));
			return -1;
		}
	}
	conn_set_class(c,conn_class_d2gs);
	conn_set_state(c,conn_state_connected);
	conn_set_d2gs_id(c,d2gs_get_id(gs));
	if (handle_d2gs_init(c)<0) {
		eventlog(eventlog_level_error, __FUNCTION__, "failed to init d2gs connection");
		return -1;
	}
	return 0;
}
예제 #6
0
static int _client_anongame_set_icon(t_connection * c, t_packet const * const packet)
{
    //BlacKDicK 04/20/2003
    unsigned int desired_icon;
    char user_icon[5];

    /*FIXME: In this case we do not get a 'count' but insted of it we get the icon
    that the client wants to set.'W3H2' for an example. For now it is ok, since they share
    the same position	on the packet*/
    desired_icon=bn_int_get(packet->u.client_findanongame.count);
    user_icon[4]=0;
    if (desired_icon==0){
	std::strcpy(user_icon,"NULL");
	eventlog(eventlog_level_info,__FUNCTION__,"[%d] Set icon packet to DEFAULT ICON [%4.4s]",conn_get_socket(c),user_icon);
    }else{
	std::memcpy(user_icon,&desired_icon,4);
	eventlog(eventlog_level_info,__FUNCTION__,"[%d] Set icon packet to ICON [%s]",conn_get_socket(c),user_icon);
    }

    account_set_user_icon(conn_get_account(c),conn_get_clienttag(c),user_icon);
    //FIXME: Still need a way to 'refresh the user/channel'
    //_handle_rejoin_command(conn_get_account(c),"");
    /* ??? channel_update_userflags() */
	conn_update_w3_playerinfo(c);

    channel_rejoin(c);
    return 0;
}
예제 #7
0
		/* Choose icon by user from profile > portrait */
		static int _client_anongame_set_icon(t_connection * c, t_packet const * const packet)
		{
			//BlacKDicK 04/20/2003
			// Modified by aancw 16/12/2014
			unsigned int desired_icon;
			char user_icon[5];
			t_account * account;

			// disable with custom icons
			if (prefs_get_custom_icons() == 1)
			{
				return 0;
			}

			/*FIXME: In this case we do not get a 'count' but insted of it we get the icon
			that the client wants to set.'W3H2' for an example. For now it is ok, since they share
			the same position	on the packet*/
			desired_icon = bn_int_get(packet->u.client_findanongame.count);
			//user_icon[4]=0;
			if (desired_icon == 0){
				std::strcpy(user_icon, "1O3W"); // 103W is equal to Default Icon
				eventlog(eventlog_level_info, __FUNCTION__, "[%d] Set icon packet to DEFAULT ICON [%4.4s]", conn_get_socket(c), user_icon);
			}
			else{
				std::memcpy(user_icon, &desired_icon, 4);
				eventlog(eventlog_level_info, __FUNCTION__, "[%d] Set icon packet to ICON [%s]", conn_get_socket(c), user_icon);
			}

			account = conn_get_account(c);
			
			// ICON SWITCH HACK PROTECTION
			if (check_user_icon(account, user_icon) == 0)
			{
				std::strcpy(user_icon, "1O3W"); // set icon to default
				eventlog(eventlog_level_info, __FUNCTION__, "[%s] \"%s\" ICON SWITCH hack attempt, icon set to default ", conn_get_username(c), user_icon);
				//conn_set_state(c,conn_state_destroy); // dont kill user session
			}

			account_set_user_icon(conn_get_account(c), conn_get_clienttag(c), user_icon);
			//FIXME: Still need a way to 'refresh the user/channel'
			//_handle_rejoin_command(conn_get_account(c),"");
			/* ??? channel_update_userflags() */
			conn_update_w3_playerinfo(c);

			channel_rejoin(c);
			return 0;
		}
예제 #8
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;
}
예제 #9
0
static int _handle_privmsg_command(t_connection * conn, int numparams, char ** params, char * text)
{
    if ((numparams>=1)&&(text))
    {
        int i;
        char ** e;

        e = irc_get_listelems(params[0]);
        /* FIXME: support wildcards! */

        /* start amadeo: code was sent by some unkown fellow of pvpgn (maybe u wanna give us your name
           for any credits), it adds nick-registration, i changed some things here and there... */
        for (i=0; ((e)&&(e[i])); i++) {
            if (strcasecmp(e[i],"NICKSERV")==0) {
                char * pass;
                char * p;

                pass = std::strchr(text,' ');
                if (pass)
                    *pass++ = '\0';

                if (strcasecmp(text,"identify")==0) {
                    switch (conn_get_state(conn)) {
                    case conn_state_bot_password:
                    {
                        if (pass) {
                            t_hash h;

                            for (p = pass; *p; p++)
                                if (std::isupper((int)*p)) *p = std::tolower(*p);
                            bnet_hash(&h,std::strlen(pass),pass);
                            irc_authenticate(conn,hash_get_str(h));
                        }
                        else {
                            message_send_text(conn,message_type_notice,NULL,"Syntax: IDENTIFY <password> (max 16 characters)");
                        }
                        break;
                    }
                    case conn_state_loggedin:
                    {
                        message_send_text(conn,message_type_notice,NULL,"You don't need to IDENTIFY");
                        break;
                    }
                    default:
                        ;
                        eventlog(eventlog_level_trace,__FUNCTION__,"got /msg in unexpected connection state (%s)",conn_state_get_str(conn_get_state(conn)));
                    }
                }
                else if (strcasecmp(text,"register")==0) {
                    unsigned int j;
                    t_hash       passhash;
                    t_account  * temp;
                    char         msgtemp[MAX_IRC_MESSAGE_LEN];
                    char       * username=(char *)conn_get_loggeduser(conn);

                    if (account_check_name(username)<0) {
                        message_send_text(conn,message_type_error,conn,"Account name contains invalid symbol!");
                        break;
                    }

                    if(!prefs_get_allow_new_accounts()) {
                        message_send_text(conn,message_type_error,conn,"Account creation is not allowed");
                        break;
                    }

                    if (!pass || pass[0]=='\0' || (std::strlen(pass)>16) ) {
                        message_send_text(conn,message_type_error,conn,"Syntax: REGISTER <password> (max 16 characters)");
                        break;
                    }

                    for (j=0; j<std::strlen(pass); j++)
                        if (std::isupper((int)pass[j])) pass[j] = std::tolower((int)pass[j]);

                    bnet_hash(&passhash,std::strlen(pass),pass);

                    snprintf(msgtemp, sizeof(msgtemp), "Trying to create account \"%s\" with password \"%s\"",username,pass);
                    message_send_text(conn,message_type_info,conn,msgtemp);

                    temp = accountlist_create_account(username,hash_get_str(passhash));
                    if (!temp) {
                        message_send_text(conn,message_type_error,conn,"Failed to create account!");
                        eventlog(eventlog_level_debug,__FUNCTION__,"[%d] account \"%s\" not created (failed)",conn_get_socket(conn),username);
                        conn_unget_chatname(conn,username);
                        break;
                    }

                    snprintf(msgtemp, sizeof(msgtemp), "Account "UID_FORMAT" created.",account_get_uid(temp));
                    message_send_text(conn,message_type_info,conn,msgtemp);
                    eventlog(eventlog_level_debug,__FUNCTION__,"[%d] account \"%s\" created",conn_get_socket(conn),username);
                    conn_unget_chatname(conn,username);
                }
                else {
                    char tmp[MAX_IRC_MESSAGE_LEN+1];
                    message_send_text(conn,message_type_notice,NULL,"Invalid arguments for NICKSERV");
                    snprintf(tmp, sizeof(tmp), ":Unrecognized command \"%s\"", text);
                    message_send_text(conn,message_type_notice,NULL,tmp);
                }
            }
            else if (conn_get_state(conn)==conn_state_loggedin) {
                if (e[i][0]=='#') {
                    /* channel message */
                    t_channel * channel;

                    if ((channel = channellist_find_channel_by_name(irc_convert_ircname(e[i]),NULL,NULL))) {
                        if ((std::strlen(text)>=9)&&(std::strncmp(text,"\001ACTION ",8)==0)&&(text[std::strlen(text)-1]=='\001')) {
                            /* at least "\001ACTION \001" */
                            /* it's a CTCP ACTION message */
                            text = text + 8;
                            text[std::strlen(text)-1] = '\0';
                            channel_message_send(channel,message_type_emote,conn,text);
                        }
                        else {
                            channel_message_log(channel, conn, 1, text);
                            channel_message_send(channel,message_type_talk,conn,text);
                        }
                    }
                    else {
                        irc_send(conn,ERR_NOSUCHCHANNEL,":No such channel");
                    }
                }
                else {
                    /* whisper */
                    t_connection * user;

                    if ((user = connlist_find_connection_by_accountname(e[i])))
                    {
                        message_send_text(user,message_type_whisper,conn,text);
                    }
                    else
                    {
                        irc_send(conn,ERR_NOSUCHNICK,":No such user");
                    }
                }
            }
        }
        if (e)
            irc_unget_listelems(e);
    }
    else
        irc_send(conn,ERR_NEEDMOREPARAMS,"PRIVMSG :Not enough parameters");
    return 0;
}
예제 #10
0
static int _handle_user_command(t_connection * conn, int numparams, char ** params, char * text)
{
    /* RFC 2812 says: */
    /* <user> <mode> <unused> :<realname>*/
    /* ircII and X-Chat say: */
    /* mz SHODAN localhost :Marco Ziech */
    /* BitchX says: */
    /* mz +iws mz :Marco Ziech */
    /* Don't bother with, params 1 and 2 anymore they don't contain what they should. */
    char * user = NULL;
    char * realname = NULL;

    if ((numparams>=3)&&(params[0])&&(text)) {
        user = params[0];
        realname = text;

        if (conn_get_user(conn)) {
            irc_send(conn,ERR_ALREADYREGISTRED,":You are already registred");
        }
        else {
            eventlog(eventlog_level_debug,__FUNCTION__,"[%d] got USER: user=\"%s\" realname=\"%s\"",conn_get_socket(conn),user,realname);
            conn_set_user(conn,user);
            conn_set_owner(conn,realname);
            if (conn_get_loggeduser(conn))
                handle_irc_welcome(conn); /* only send the welcome if we have USER and NICK */
        }
    }
    else {
        irc_send(conn,ERR_NEEDMOREPARAMS,"USER :Not enough parameters");
    }
    return 0;
}
예제 #11
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;
		}
예제 #12
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;
}
예제 #13
0
extern int bits_route_add(t_uint16 bits_addr, t_connection * conn)
{
	t_bits_routing_table_entry * rte;

	if (!conn) {
		eventlog(eventlog_level_error,"bits_route_add","got NULL connection");
		return -1;
	}
	if ((bits_addr==BITS_ADDR_PEER)||(bits_addr==BITS_ADDR_MASTER)||(bits_addr==BITS_ADDR_BCAST)) {
	/*	eventlog(eventlog_level_warn,"bits_route_add","adding routes for special addresses would make no sense"); */
		return 0;
	}
	rte = bits_route_find(bits_addr);
	if (rte) {
		if (rte->conn == conn) return 0;
		eventlog(eventlog_level_debug,"bits_route_add","changing existing route for 0x%04x from [%d] to [%d].",bits_addr,conn_get_socket(rte->conn),conn_get_socket(conn));
		rte->conn = conn;
	} else {
		eventlog(eventlog_level_debug,"bits_route_add","adding route for 0x%04x to [%d].",bits_addr,conn_get_socket(conn));
		rte = malloc(sizeof(t_bits_routing_table_entry));
		if (!rte) {
			eventlog(eventlog_level_error,"bits_route_add","malloc failed: %s",strerror(errno));
			return -1;
		}
		rte->bits_addr = bits_addr;
		rte->conn = conn;
		list_append_data(bits_routing_table,rte);
	}
	return 0;
}
예제 #14
0
extern int handle_init_packet(t_connection * c, t_packet const * const packet)
{
    if (!c)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c));
	return -1;
    }
    if (!packet)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c));
	return -1;
    }
    if (packet_get_class(packet)!=packet_class_init)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet));
        return -1;
    }
    
    switch (packet_get_type(packet))
    {
    case CLIENT_INITCONN:
	switch (bn_byte_get(packet->u.client_initconn.class))
	{
	case CLIENT_INITCONN_CLASS_BNET:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated bnet connection",conn_get_socket(c));
	    conn_set_state(c,conn_state_connected);
	    conn_set_class(c,conn_class_bnet);

	    break;

	case CLIENT_INITCONN_CLASS_FILE:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated file download connection",conn_get_socket(c));
	    conn_set_state(c,conn_state_connected);
	    conn_set_class(c,conn_class_file);
	    
	    break;
	    
	case CLIENT_INITCONN_CLASS_BOT:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated chat bot connection",conn_get_socket(c));
	    conn_set_state(c,conn_state_connected);
	    conn_set_class(c,conn_class_bot);
	    
	    break;
	    
	case CLIENT_INITCONN_CLASS_TELNET:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated telnet connection",conn_get_socket(c));
	    conn_set_state(c,conn_state_connected);
	    conn_set_class(c,conn_class_telnet);
	    
	    break;

        case CLIENT_INITCONN_CLASS_D2CS_BNETD:
            {
              eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated d2cs_bnetd connection",conn_get_socket(c));

              if (!(realmlist_find_realm_by_ip(conn_get_addr(c))))
              {
                 eventlog(eventlog_level_info,__FUNCTION__, "[%d] d2cs connection from unknown ip address %s",conn_get_socket(c),addr_num_to_addr_str(conn_get_addr(c),conn_get_port(c)));
                 return -1;
              }

              conn_set_state(c,conn_state_connected);
              conn_set_class(c,conn_class_d2cs_bnetd);
              if (handle_d2cs_init(c)<0)
              {
                  eventlog(eventlog_level_info,__FUNCTION__,"faild to init d2cs connection");
                  return -1;
              }
           }
           break;
	    
	case CLIENT_INITCONN_CLASS_ENC:
	    eventlog(eventlog_level_info,__FUNCTION__,"[%d] client initiated encrypted connection (not supported)",conn_get_socket(c));
	    return -1;

	default:
	    eventlog(eventlog_level_error,__FUNCTION__,"[%d] client requested unknown class 0x%02x (length %d) (closing connection)",conn_get_socket(c),(unsigned int)bn_byte_get(packet->u.client_initconn.class),packet_get_size(packet));
	    return -1;
	}
	break;
    default:
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown init packet type 0x%04x, len %u",conn_get_socket(c),packet_get_type(packet),packet_get_size(packet));
	return -1;
    }
    
    return 0;
}
예제 #15
0
파일: file.cpp 프로젝트: DizKragnet/pvpgn
/* 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;
}
예제 #16
0
파일: handle_bot.c 프로젝트: 91D2/pvpgn
extern int handle_bot_packet(t_connection * c, t_packet const * const packet)
{
    t_packet * rpacket;
    
    if (!c)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL connection",conn_get_socket(c));
	return -1;
    }
    if (!packet)
    {
	eventlog(eventlog_level_error,__FUNCTION__,"[%d] got NULL packet",conn_get_socket(c));
	return -1;
    }
    if (packet_get_class(packet)!=packet_class_raw)
    {
        eventlog(eventlog_level_error,__FUNCTION__,"[%d] got bad packet (class %d)",conn_get_socket(c),(int)packet_get_class(packet));
        return -1;
    }
    
    {
	char const * const linestr=packet_get_str_const(packet,0,MAX_MESSAGE_LEN);
	
	if (packet_get_size(packet)<2) /* empty line */
	    return 0;
	if (!linestr)
	{
	    eventlog(eventlog_level_warn,__FUNCTION__,"[%d] line too long",conn_get_socket(c));
	    return 0;
	}
	
	switch (conn_get_state(c))
	{
	case conn_state_connected:
	    conn_add_flags(c,MF_PLUG);
	    conn_set_clienttag(c,CLIENTTAG_BNCHATBOT_UINT);
	    
	    {
		char const * temp=linestr;
		
		if (temp[0]=='\004') /* FIXME: no echo, ignore for now (we always do no echo) */
		    temp = &temp[1];
		
		if (temp[0]=='\0') /* empty line */
		{
		    conn_set_state(c,conn_state_bot_username); /* don't look for ^D or reset tag and flags */
		    break;
		}
		
		conn_set_state(c,conn_state_bot_password);
		
		if (conn_set_loggeduser(c,temp)<0)
		    eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),temp);
		
		{
		    char const * const msg="\r\nPassword: "******"[%d] could not create rpacket",conn_get_socket(c));
			break;
		    }
#if 1 /* don't echo */
		    packet_append_ntstring(rpacket,conn_get_loggeduser(c));
#endif
		    packet_append_ntstring(rpacket,msg);
		    conn_push_outqueue(c,rpacket);
		    packet_del_ref(rpacket);
		}
	    }
	    break;
	    
	case conn_state_bot_username:
	    conn_set_state(c,conn_state_bot_password);
	    
	    if (conn_set_loggeduser(c,linestr)<0)
		eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not set username to \"%s\"",conn_get_socket(c),linestr);
	    
	    {
		char const * const temp="\r\nPassword: "******"[%d] could not create rpacket",conn_get_socket(c));
		    break;
		}
#if 1 /* don't echo */
		packet_append_ntstring(rpacket,linestr);
#endif
		packet_append_ntstring(rpacket,temp);
		conn_push_outqueue(c,rpacket);
		packet_del_ref(rpacket);
	    }
	    break;
	    
	case conn_state_bot_password:
	    {
		char const * const tempa="\r\nLogin failed.\r\n\r\nUsername: "******"\r\nAccount has no bot access.\r\n\r\nUsername: "******"[%d] could not create rpacket",conn_get_socket(c));
			break;
		    }
		    
		    packet_append_ntstring(rpacket,tempa);
		    conn_push_outqueue(c,rpacket);
		    packet_del_ref(rpacket);
		    break;
		}
		if (connlist_find_connection_by_accountname(loggeduser))
		{
		    eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (already logged in)",conn_get_socket(c),loggeduser);
		    conn_set_state(c,conn_state_bot_username);
		    
		    if (!(rpacket = packet_create(packet_class_raw)))
		    {
			eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c));
			break;
		    }
		    
		    packet_append_ntstring(rpacket,tempa);
		    conn_push_outqueue(c,rpacket);
		    packet_del_ref(rpacket);
		    break;
		}
		if (!(account = accountlist_find_account(loggeduser)))
		{
			eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (bad account)",conn_get_socket(c),loggeduser);
			conn_set_state(c,conn_state_bot_username);
			
			if (!(rpacket = packet_create(packet_class_raw)))
			{
			    eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c));
			    break;
			}
			
			packet_append_ntstring(rpacket,tempa);
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
		    break;
		}
		if ((oldstrhash1 = account_get_pass(account)))
		{
		    if (hash_set_str(&oldpasshash1,oldstrhash1)<0)
		    {
			eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (corrupted passhash1?)",conn_get_socket(c),loggeduser);
			conn_set_state(c,conn_state_bot_username);
			
			if (!(rpacket = packet_create(packet_class_raw)))
			{
			    eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c));
			    break;
			}
			
			packet_append_ntstring(rpacket,tempa);
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
			break;
		    }

                    testpass = xstrdup(linestr);
		    {
			unsigned int i;
			
			for (i=0; i<strlen(testpass); i++)
			    if (isupper((int)testpass[i]))
				testpass[i] = tolower((int)testpass[i]);
		    }
		    if (bnet_hash(&trypasshash1,strlen(testpass),testpass)<0) /* FIXME: force to lowercase */
		    {
			eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (unable to hash password)",conn_get_socket(c), loggeduser);
			conn_set_state(c,conn_state_bot_username);

			xfree((void *)testpass);
			
			if (!(rpacket = packet_create(packet_class_raw)))
			{
			    eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c));
			    break;
			}
			
			packet_append_ntstring(rpacket,tempa);
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
			break;
		    }
		    xfree((void *)testpass);
		    if (hash_eq(trypasshash1,oldpasshash1)!=1)
		    {
			eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (wrong password)",conn_get_socket(c), loggeduser);
			conn_set_state(c,conn_state_bot_username);
			
			if (!(rpacket = packet_create(packet_class_raw)))
			{
			    eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c));
			    break;
			}
			
			packet_append_ntstring(rpacket,tempa);
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
			break;
		    }
		    
		    
		    if (account_get_auth_botlogin(account)!=1) /* default to false */
		    {
			eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (no bot access)",conn_get_socket(c), loggeduser);
			conn_set_state(c,conn_state_bot_username);
			
			if (!(rpacket = packet_create(packet_class_raw)))
			{
			    eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c));
			    break;
			}
			
			packet_append_ntstring(rpacket,tempb);
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
			break;
		    }
		    else if (account_get_auth_lock(account)==1) /* default to false */
		    {
			eventlog(eventlog_level_info,__FUNCTION__,"[%d] bot login for \"%s\" refused (this account is locked)",conn_get_socket(c), loggeduser);
			conn_set_state(c,conn_state_bot_username);
			
			if (!(rpacket = packet_create(packet_class_raw)))
			{
			    eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c));
			    break;
			}
			
			packet_append_ntstring(rpacket,tempb);
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
			break;
		    }
		    
		    eventlog(eventlog_level_info,__FUNCTION__,"[%d] \"%s\" bot logged in (correct password)",conn_get_socket(c), loggeduser);
		}
		else
		{
		    eventlog(eventlog_level_info,__FUNCTION__,"[%d] \"%s\" bot logged in (no password)",conn_get_socket(c), loggeduser);
		}
		    if (!(rpacket = packet_create(packet_class_raw))) /* if we got this far, let them log in even if this fails */
			eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not create rpacket",conn_get_socket(c));
		    else
		    {
			packet_append_ntstring(rpacket,"\r\n");
			conn_push_outqueue(c,rpacket);
			packet_del_ref(rpacket);
		    }

			bnetd_log(loggeduser, addr_num_to_ip_str(conn_get_addr(c)), "BOT", "LOGIN", NULL, 1, 0);
		    conn_login(c,account,loggeduser);

		    message_send_text(c,message_type_uniqueid,c,loggeduser);
		    		    
		    if (conn_set_channel(c,CHANNEL_NAME_CHAT)<0)
			conn_set_channel(c,CHANNEL_NAME_BANNED); /* should not fail */
	    }
	    break;
	    
	case conn_state_loggedin:
	    {
		t_channel const * channel;
		
		conn_set_idletime(c);
		
		if ((channel = conn_get_channel(c)))
		    channel_message_log(channel,c,1,linestr);
		/* we don't log game commands currently */
		
		if (linestr[0]=='/')
		    handle_command(c,linestr);
		else
		    if (channel && !conn_quota_exceeded(c,linestr))
			channel_message_send(channel,message_type_talk,c,linestr);
		    /* else discard */
	    }
	    break;
	    
	default:
	    eventlog(eventlog_level_error,__FUNCTION__,"[%d] unknown bot connection state %d",conn_get_socket(c),(int)conn_get_state(c));
	}
    }
    
    return 0;
}
예제 #17
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;
}
예제 #18
0
파일: server.c 프로젝트: cooljeanius/bnetd
static int sd_tcpinput(int csocket, t_connection * c)
{
    unsigned int currsize;
    t_packet *   packet;

    currsize = conn_get_in_size(c);

    if (!*conn_get_in_queue(c))
    {
	switch (conn_get_class(c))
	{
	case conn_class_init:
	    if (!(packet = packet_create(packet_class_init)))
	    {
		eventlog(eventlog_level_error,"sd_tcpinput","could not allocate init packet for input");
		return -1;
	    }
	    break;
         case conn_class_d2cs_bnetd:
            if (!(packet = packet_create(packet_class_d2cs_bnetd)))
            {
                eventlog(eventlog_level_error,"server_process","could not allocate d2cs_bnetd packet");
                return -1;
            }
            break;
	case conn_class_bnet:
	    if (!(packet = packet_create(packet_class_bnet)))
	    {
		eventlog(eventlog_level_error,"sd_tcpinput","could not allocate bnet packet for input");
		return -1;
	    }
	    break;
	case conn_class_file:
	    if (!(packet = packet_create(packet_class_file)))
	    {
		eventlog(eventlog_level_error,"sd_tcpinput","could not allocate file packet for input");
		return -1;
	    }
	    break;
	case conn_class_bits:
	    if (!(packet = packet_create(packet_class_bits)))
	    {
		eventlog(eventlog_level_error,"sd_tcpinput","could not allocate BITS packet for input");
		return -1;
	    }
	    break;
	case conn_class_defer:
	case conn_class_bot:
	case conn_class_irc:
	case conn_class_telnet:
	    if (!(packet = packet_create(packet_class_raw)))
	    {
		eventlog(eventlog_level_error,"sd_tcpinput","could not allocate raw packet for input");
		return -1;
	    }
	    packet_set_size(packet,1); /* start by only reading one char */
	    break;
	case conn_class_auth:
	    if (!(packet = packet_create(packet_class_auth)))
	    {
		eventlog(eventlog_level_error,"sd_tcpinput","could not allocate auth packet for input");
		return -1;
	    }
	    break;
	default:
	    eventlog(eventlog_level_error,"sd_tcpinput","[%d] connection has bad class (closing connection)",conn_get_socket(c));
	    conn_destroy(c);
	    return -1;
	}
	queue_push_packet(conn_get_in_queue(c),packet);
	packet_del_ref(packet);
	if (!*conn_get_in_queue(c))
	    return -1; /* push failed */
	currsize = 0;
    }

    packet = queue_peek_packet((t_queue const * const *)conn_get_in_queue(c)); /* avoid warning */
    switch (net_recv_packet(csocket,packet,&currsize))
    {
    case -1:
	eventlog(eventlog_level_debug,"sd_tcpinput","[%d] read FAILED (closing connection)",conn_get_socket(c));
	conn_destroy(c);
	return -1;

    case 0: /* still working on it */
	/* eventlog(eventlog_level_debug,"sd_tcpinput","[%d] still reading \"%s\" packet (%u of %u bytes so far)",conn_get_socket(c),packet_get_class_str(packet),conn_get_in_size(c),packet_get_size(packet)); */
	conn_set_in_size(c,currsize);
	break;

    case 1: /* done reading */
	switch (conn_get_class(c))
	{
	case conn_class_defer:
	    {
		unsigned char const * const temp=packet_get_raw_data_const(packet,0);

		eventlog(eventlog_level_debug,"sd_tcpinput","[%d] got first packet byte %02x",conn_get_socket(c),(unsigned int)temp[0]);
		if (temp[0]==(unsigned char)0xff) /* HACK: thankfully all bnet packet types end with ff */
		{
		    conn_set_class(c,conn_class_bnet);
		    conn_set_in_size(c,currsize);
		    packet_set_class(packet,packet_class_bnet);
		    eventlog(eventlog_level_debug,"sd_tcpinput","[%d] defered connection class is bnet",conn_get_socket(c));
		}
		else
		{
		    conn_set_class(c,conn_class_auth);
		    conn_set_in_size(c,currsize);
		    packet_set_class(packet,packet_class_auth);
		    eventlog(eventlog_level_debug,"sd_tcpinput","[%d] defered connection class is auth",conn_get_socket(c));
		}
	    }
	    break;

	case conn_class_bot:
	case conn_class_telnet:
	    if (currsize<MAX_PACKET_SIZE) /* if we overflow, we can't wait for the end of the line.
					     handle_*_packet() should take care of it */
	    {
		char const * const temp=packet_get_raw_data_const(packet,0);

		if ((temp[currsize-1]=='\003')||(temp[currsize-1]=='\004')) {
		    /* we have to ignore these special characters, since
		     * some bots even send them after login (eg. UltimateBot)
		     */
		    currsize--;
		    break;
		}

		if (temp[currsize-1]!='\r' && temp[currsize-1]!='\n')
		{
		    conn_set_in_size(c,currsize);
		    packet_set_size(packet,currsize+1);
		    break; /* no end of line, get another char */
		}
	    }
	    /* got a complete line or overflow, so: */
	    /*FALLTHRU*/
	default:
	    packet = queue_pull_packet(conn_get_in_queue(c));

	    if (hexstrm)
	    {
		fprintf(hexstrm,"%d: recv class=%s[0x%02x] type=%s[0x%04x] length=%u\n",
			csocket,
			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_const(packet,0),packet_get_size(packet));
	    }

	    if (conn_get_class(c)==conn_class_bot ||
		conn_get_class(c)==conn_class_telnet) /* NUL terminate the line to make life easier */
	    {
		char * const temp=packet_get_raw_data(packet,0);

		if (temp[currsize-1]=='\r' || temp[currsize-1]=='\n')
		    temp[currsize-1] = '\0'; /* have to do it here instead of above so everything
						is intact for the hexdump */
	    }

	    {
		int ret;

		switch (conn_get_class(c))
		{
		case conn_class_bits:
#ifdef WITH_BITS
		    ret = handle_bits_packet(c,packet);
#else
		    eventlog(eventlog_level_error,"sd_tcpinput","[%d] BITS not enabled (closing connection)",conn_get_socket(c));
		    ret = -1;
#endif
		    break;
		case conn_class_init:
		    ret = handle_init_packet(c,packet);
		    break;
		case conn_class_bnet:
		    ret = handle_bnet_packet(c,packet);
		    break;
                case conn_class_d2cs_bnetd:
                    ret = handle_d2cs_packet(c,packet);
                    break;
		case conn_class_bot:
		    ret = handle_bot_packet(c,packet);
		    break;
		case conn_class_telnet:
		    ret = handle_telnet_packet(c,packet);
		    break;
		case conn_class_file:
		    ret = handle_file_packet(c,packet);
		    break;
		case conn_class_auth:
		    ret = handle_auth_packet(c,packet);
		    break;
		case conn_class_irc:
		    ret = handle_irc_packet(c,packet);
		    break;
		default:
		    eventlog(eventlog_level_error,"sd_tcpinput","[%d] bad packet class %d (closing connection)",conn_get_socket(c),(int)packet_get_class(packet));
		    ret = -1;
		}
		packet_del_ref(packet);
		if (ret<0)
		{
		    conn_destroy(c);
		    return -1;
		}
	    }

	    conn_set_in_size(c,0);
	}
    }

    return 0;
}