Beispiel #1
0
static void ircd(void * data, char * name) {
	fs_node_t * tty = data;
	char * buf = malloc(4096);

	while (1) {
		char * result = fgets(buf, 4095, irc_socket);
		if (!result) continue;
		size_t len = strlen(buf);
		if (!len) continue;

		handle_irc_packet(tty, len, (unsigned char *)buf);
	}
}
Beispiel #2
0
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;
}